home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr22 / bytewb.zip / BYTEWB.PAS < prev    next >
Pascal/Delphi Source File  |  1993-06-24  |  118KB  |  4,049 lines

  1. {**********************************}
  2. {   BYTE Windows Benchmarks        }
  3. {   Version 1.0                    }
  4. {   July 1992                      }
  5. {   Turbo Pascal Version by        }
  6. {   Rick Grehan                    }
  7. {   Version 1.1 Revisions by       }
  8. {   Raymond GA Cote                }
  9. {     Appropriate Solutions, Inc.  }
  10. {**********************************}
  11. { HISTORY:
  12.   93Jan27 RGAC -- Appropriate Solutions, Inc.
  13.     Added following changes culminating on this date.
  14.     1: -L on command line will cause tests to be run automatically,
  15.        sent to a log file, and program to terminate.
  16.     2: a filename on the command line will be used for logfile, otherwise
  17.        we will use a default name.
  18.     3: Window is now set to 640 by 480.
  19.     4: Did not change algorithm in sequential file I/O. Simply limited
  20.        writing within array bounds and started/stopped timer.
  21.     5: Since sfio was setup as a single reportable number I left it that way.
  22.     6: System no longer appears to be crashing. I've run it several hours
  23.        without problems. It still needs, however, error checking and
  24.        handling routines.
  25.     7: Sfile_io test was not set-up as a timed test. Rather it runs once
  26.        and one-time experiment is used for a timing value. I did not change this.
  27.     8: Rfile_io is configured as a timed test. However, I did not alter
  28.        the user interface to allow timing data to be entered.
  29.        However, I do use the global variables for timing the test.
  30.     9: Random file i/o routine was translated from Byte Low level Benchmarks.
  31.        It uses a single-character array (it is never changed).
  32.        This may cause problems with upcoming intelligent cache controllers
  33.        which may not decide to actually write the information.
  34.        Needs to be changed in future software release.
  35.    10: Lab needs to determine test environment for running windows benchmark.
  36.        SmartDrive sizes, etc.
  37.    11: Random I/O currently set to run for 30 seconds. This produces 965 Kbytes/second on
  38.        my system which is just slightly slower than the BBENCH low-level throughput value.
  39.        The following values were received from the test at varying times:
  40.            15s  1,421 Kbytes/sec
  41.            30s    965 Kbytes/sec
  42.            45s    728 Kbytes/sec
  43.            60s    610 Kbytes/sec
  44.        Current interface does not allow time to be set from this user interface.
  45.    12: Added a 5-second delay to start of random file i/o test. My reasoning is as follows:
  46.        Random file i/o runs immediately after the sequential file i/o. System may still be
  47.        flushing the cache from the sequential test. This will have a dramatic impact on the
  48.        test results.
  49.        Specifically. Running the random test by itself will produce different results than whe
  50.        they are run in a batch.
  51.    13: Log file is timestamped and contains its  own name.
  52.    14: Local Memory test no longer locks up the system.
  53.    15: Put local memory test into iteration loop. Did quick check to see that it performed
  54.        properly. Verified that calcluated output shown in reports is valid.
  55.    16: Put global memory test into iteration loop. Reported numbers are very low.
  56.        Test slows down dramatically between iterations. First iteration takes 1.4
  57.        seconds, last iteration takes 6.2 seconds.
  58.        I've not explored the problem.
  59.    17: Fixed improper addition (or nonaddition) of '0' to minutes in timelog.
  60.    18: Instead of handling display of external log files, I've allowed you to view
  61.        results of all tests up to this point. Viewing also logs all test results
  62.        to the log file.
  63.    19: Changed displayBenchLine so it tracks its own position.
  64.        Added InitBenchDisplay which sets-up the variables.
  65.        Should be called before each new set of screen displays.
  66.        Note: you won't get scrolling with these routines.
  67.    20: Allow user to enter name of logfile. Currently only accepts
  68.        eight character name and three-character extension. No error checking
  69.        done in current code. Caveat Emptor.
  70.  
  71.    ============= that's it for now, I'll come back and polish a few
  72.                  things in about a week. ==
  73. }
  74.  
  75. {
  76.   Things that still need doing:
  77.     1:   File I/O error handling.
  78.     2:   Memory allocation error handling.
  79.     3:   User interface is much too "cute".
  80.     4:   Need to follow Windows GUI standards.
  81.     5:   Still need processor identification.
  82.     7:   Display system configuration.
  83.     10:  Final testing.
  84.     11:  Validation from the field.
  85.     13:  Determine if global memory test is functioning properly.
  86.     14:  Determine when window is activated and update the information.
  87.     15:  Need to not use the Microsoft trademark as minimized icon.
  88. }
  89.  
  90. program ByteWbench;
  91.  
  92. {$R BYTEWB }     { Our resource file is BYTEWB.RES }
  93. {$X+ }                { Enable extended syntax }
  94. uses WinTypes, WinProcs, Strings, WinDos;
  95.  
  96. (**********************
  97.  ** GLOBAL CONSTANTS **
  98.  **********************)
  99. CONST
  100.     NULL = 0;
  101.     ID_PIXEL_BUTTON = 101;
  102.     ID_LINES_BUTTON = 102;
  103.     ID_RECTS_BUTTON = 103;
  104.     ID_POLYS_BUTTON = 104;
  105.     ID_ARCE_BUTTON = 105;
  106.     ID_BITBLT_BUTTON = 106;
  107.     ID_LMEM_BUTTON = 107;
  108.     ID_GMEM_BUTTON = 108;
  109.     ID_SFIO_BUTTON = 109;
  110.     ID_RFIO_BUTTON = 110;
  111.     ID_TEXT_BUTTON = 111;
  112.  
  113.     ID_PIXEL_SECS = 120;
  114.     ID_LINE_SECS = 121;
  115.     ID_RECT_SECS = 122;
  116.     ID_POLY_SECS = 123;
  117.     ID_ARCE_SECS = 124;
  118.     ID_BITBLT_SECS = 125;
  119.     ID_LMEM_SECS = 126;
  120.     ID_GMEM_SECS = 127;
  121.   ID_TEXT_SECS = 128;
  122.  
  123.     IDM_SETLOG = 201;
  124.     IDM_DISPLOG = 202;
  125.     IDM_EXIT = 203;
  126.   IDM_INFO = 204;
  127.   IDM_COMPINFO = 205;
  128.     IDM_CONFBENCHES = 211;
  129.     IDM_SYSCONF = 212;
  130.     IDM_SETDEFS = 213;
  131.     IDM_EXECUTE = 221;
  132.  
  133.     IDB_OK = 150;
  134.     IDB_CANCEL = 151;
  135.  
  136.   IDL_OK = 101;
  137.   IDL_CANCEL = 103;
  138.   IDL_LOGFIELD = 102;
  139.  
  140. (**
  141.  ** Number of timer array elements.
  142.  **)
  143.     time_array_elems = 4;
  144.  
  145. (**
  146.  ** Minimum number of seconds for tests.
  147.  ** These define the minimum that the user can set a test
  148.  ** to, the idea being that anything less makes the results
  149.  ** questionable.
  150.  *)
  151.     min_pixel_secs = 30;
  152.   min_line_secs = 30;
  153.     min_rect_secs = 30;
  154.     min_poly_secs = 30;
  155.     min_arce_secs = 30;
  156.     min_bitblt_secs = 30;
  157.     min_lmem_secs = 30;
  158.     min_gmem_secs = 30;
  159.   min_text_secs = 30;
  160.   min_rfile_io_secs = 30;
  161.   min_sfile_io_secs = 30;
  162.  
  163. (**
  164.  ** These constants set the number of "things done" per
  165.  ** iteration.  In a future version, it might be a good
  166.  ** idea to have these fellows become minimum values and
  167.  ** let the user adjust the number of repetitions per
  168.  ** iteration.
  169.  *)
  170.     pixels_per_iter =1000;       { # of pixels per iteration }
  171.     lines_per_iter = 1000;    { # of lines per iteration }
  172.     polys_per_iter = 20;        { # of poly lines per iteration }
  173.     rects_per_iter = 1000;    { # of rects per iteration }
  174.   ellps_per_iter = 1000;        { # of ellipses per iteration }
  175.   bmap_points = 1000;                { # of bitmap points per iteration }
  176.   lmems_per_iter = 1;                { # of local memory tests per iter }
  177.   gmems_per_iter = 1;                { # of global memory tests per iter }
  178.   text_per_iter = 400;            { # of text strings per iteration }
  179.   { the following bizarre value comes from the use of a nonBinary-power
  180.     value as the upper bounds of the sequential I/O test. I've left
  181.     it here since that is how the code was presented. rgac }
  182.   sfio_bytes_per_iter = 19995904 * 2;  {same # bytes for write and read}
  183.  
  184.   disk_space_needed = 6000 * 1024;        { 6 MB }
  185.  
  186.   bmap_size = 72;                        { Bitmap x & y dimension }
  187.  
  188.   (*
  189.    ** NOTE: The pre-release version of the benchmarks used
  190.    ** pen styles other than the ps_Solid.  This caused problems
  191.    ** with some accelerator cards, which had a hard time doing
  192.    ** ps_Dash and ps_Dot pens.  The results were skewed [how
  193.    ** many times have you seen dashed or dotted lines onscreen?].
  194.    ** So, all pens are now ps_Solid. --RG
  195.    *)
  196.  
  197.     pen_style: ARRAY [0..2] OF Integer =
  198.             ( ps_Solid, ps_Dash, ps_Dot );
  199.  
  200. (**
  201.  ** Brush types.
  202.  ** NOTE: The benchmarks have a larger number of null brushes so
  203.  ** that they tend to test empy polygons more frequently than
  204.  ** filled ones.  The actual ratio should -- at some time in
  205.  ** the future -- be determined by profiling.
  206.  **)
  207.   brush_style: ARRAY [0..9] OF Integer =
  208.       ( Black_Brush, Null_Brush, DkGray_Brush, Null_Brush,
  209.       Gray_Brush, Hollow_Brush,
  210.         LtGray_Brush, Null_Brush, White_Brush, Null_Brush );
  211.  
  212. (**
  213.  ** The following array of edit box id numbers are used
  214.  ** to facilitate the scanning of edit boxes on the
  215.  ** configuration scree.
  216.  **)
  217.     edit_box_ids: ARRAY[0..8] OF Word =
  218.          ( ID_PIXEL_SECS, ID_LINE_SECS, ID_RECT_SECS,
  219.              ID_POLY_SECS, ID_ARCE_SECS, ID_BITBLT_SECS,
  220.              ID_LMEM_SECS, ID_GMEM_SECS, ID_TEXT_SECS );
  221.  
  222. (**
  223.  ** The following array is used to scan edit boxes
  224.  ** and verify that their contents are above the
  225.  ** allowed minimum.
  226.  **)
  227.     edit_box_mins: ARRAY[0..8] OF Word =
  228.         ( min_pixel_secs, min_line_secs, min_rect_secs,
  229.             min_poly_secs, min_arce_secs, min_bitblt_secs,
  230.             min_lmem_secs, min_gmem_secs, min_text_secs );
  231.  
  232. (**
  233.  ** The following array is used to scan the checkbox
  234.  ** buttons.
  235.  ** NOTE: It's ordering is important!!  It must
  236.  ** correspond to the following set of constants.
  237.  ** i.e., if pixel_test_id=1, then the first member
  238.  ** of the button_id array MUST be ID__PIXEL_BUTTON.
  239.  **)
  240.     button_ids: ARRAY[1..11] OF Word =
  241.         ( ID_PIXEL_BUTTON, ID_LINES_BUTTON, ID_RECTS_BUTTON,
  242.             ID_POLYS_BUTTON, ID_ARCE_BUTTON, ID_BITBLT_BUTTON,
  243.             ID_LMEM_BUTTON, ID_GMEM_BUTTON, ID_SFIO_BUTTON,
  244.             ID_RFIO_BUTTON, ID_TEXT_BUTTON );
  245.  
  246. (**
  247.  ** Test ID numbers.
  248.  **)
  249.     pixel_test_id = 1;
  250.     line_test_id = 2;
  251.     rect_test_id = 3;
  252.     poly_test_id = 4;
  253.     arce_test_id = 5;
  254.     bitblt_test_id = 6;
  255.     lmem_test_id = 7;
  256.     gmem_test_id = 8;
  257.     sfio_test_id = 9;
  258.     rfio_test_id = 10;
  259.     texto_test_id = 11;
  260.   dtext_test_id = 12;
  261.  
  262. (**
  263.  ** Test id max.  Adjust this as you add more tests.
  264.  **)
  265.     max_test_id = 12;
  266.   max_num_tests = max_test_id;
  267.  
  268. (**
  269.  ** Preferences.  This is a section to be expanded in
  270.  ** the future.
  271.  **)
  272.   pref_clipamt_id = 1;                    { Do clipping }
  273.  
  274.   max_pref_id = 1;
  275.  
  276. (**
  277.  ** Following constant array holds the number of "things per
  278.  ** iteration" of each test.
  279.  **)
  280.  items_per_iter: ARRAY[1..max_test_id] OF LongInt =
  281.      ( pixels_per_iter, lines_per_iter, rects_per_iter,
  282.     polys_per_iter, ellps_per_iter, bmap_points,
  283.     lmems_per_iter, gmems_per_iter,
  284.     1, 1,
  285.     text_per_iter, text_per_iter );
  286.  
  287. (**
  288.  ** Following constants set default values for parameter
  289.  ** of many of the benchmarks.  These are initially loaded
  290.  ** into variables.
  291.  ** NOTE: Future version of benchmarks should make these
  292.  ** values user-modifiable.
  293.  **)
  294.     { Local memory benchmark }
  295.     max_local_memitems = 256;
  296.     max_local_memsize = 30000;
  297.  
  298.   max_global_memitems = 512;
  299.   max_global_memsize = 1000000;
  300.  
  301. (**
  302.  ** Text strings for displaying results.
  303.  **)
  304.   test_name: ARRAY [1..max_test_id] OF String[20] =
  305.       ( 'Pixels: ', 'Lines: ', 'Rectangles: ', 'Polygons: ',
  306.       'Ellipses: ', 'BitBlts: ', 'Loc. Memory: ',
  307.       'Glob. Memory: ','Seq. File I/O: ', 'Rand. File I/O: ',
  308.       'TextOut: ', 'DrawText: ' );
  309.  
  310. (**
  311.  ** Strings used in the TEXT benchmarks.
  312.  **)
  313.   bench_strs: ARRAY [0..5] OF String[50] =
  314.       ( 'The Quick Brown Fox Jumped Over The Lazy Dog',
  315.       'Never Eat Anything Bigger Than Your HEAD',
  316.       'NEVER hold an electrical wire in your mouth',
  317.       'Where Do Pixels Go When Not Being Lit?',
  318.       'Do not lean forward as the bus pulls up!',
  319.       'Fried Rice should be eaten through the mouth');
  320.  
  321.   DefLogName: String[13] = 'winbench.log';
  322.   DefCompName: String[13] = 'wincomp.dat';
  323.  
  324.   { Following used as a cheap source of dashed lines and blanks }
  325.   dashstr: PChar ='------------------------------------------------------------'#0;
  326.   blankstr: PChar = '                                                             '#0;
  327.  
  328.  
  329.   { Following defines # of bytes to set aside for each
  330.     entry in the data comparison file. }
  331.   compblocksize = 130;
  332.  
  333. (**********************
  334.  ** TYPE DEFINITIONS **
  335.  **********************)
  336. TYPE
  337.     ByteRec = RECORD            { Chop a word into 2 bytes }
  338.         lo, hi: Byte;
  339.     END;
  340.  
  341.     WordRec = RECORD            { Chop a LongInt into 2 words }
  342.         lo, hi: Word;
  343.     END;
  344.  
  345.   BigFileBuffType = ARRAY[0..39999] OF Char;
  346.  
  347.   FileName = ARRAY[0..14] OF Char;
  348.  
  349.   { The following item, CompData, defines the record
  350.     layout of each entry in the comparison file. }
  351.   CompData = RECORD
  352.       description: ARRAY[0..70] of Char;
  353.       sysname:    ARRAY[0..20] OF Char;
  354.     testresult:    ARRAY[1..max_test_id] OF Real;
  355.   END;
  356.  
  357.   PCompData = ^CompData;
  358.  
  359. (**********************
  360.  ** GLOBAL VARIABLES **
  361.  **********************)
  362. VAR
  363.  
  364.     pens: ARRAY [0..7] OF HPen;            { Handles for pens }
  365.  
  366.     stopwatch: Longint;                       { Timer stopwatch holding var. }
  367.  
  368. (**
  369.  ** The follow arrays keep track of elapsed time and number
  370.  ** of iterations for each test.
  371.  **)
  372.   elapsedtsecarray: ARRAY[1..max_test_id] OF Longint;
  373.     iterarray: ARRAY[1..max_test_id] OF Longint;
  374.  
  375. (**
  376.  ** Next items are special.  The text benchmarks actually
  377.  ** capture separate numbers.  One set for TextOut and
  378.  ** another for DrawText.  In the results, the elapsed
  379.  ** arrays hold the results for DrawText.  These next
  380.  ** variables hold the TextOut results.
  381.  **)
  382.   textoutelapsedtsecs: Longint;
  383.   textoutiters: Longint;
  384.  
  385.   randl: ARRAY [0..1] OF LongInt; { Random number storage }
  386.  
  387.     HByteWin: HWnd;                                    { Handle to parent window }
  388.     pstruct: TPaintStruct;                    { Paint structure }
  389.  
  390. (**
  391.  ** do_test_flags is an array that shows what tests
  392.  ** are to be executed.
  393.  ** tdo_test_flags holds a copy of the above array during
  394.  ** editing of the configuration information, and allows
  395.  ** the user to cancel his settings.
  396.  **)
  397.     do_test_flags: ARRAY[1..max_test_id] OF Bool;
  398.     tdo_test_flags: ARRAY[1..max_test_id] OF Bool;
  399.  
  400.  
  401.     pixel_secs: Word;     { # of seconds to do pixels test }
  402.     line_secs: Word;      { # of seconds to do lines test }
  403.     rect_secs: Word;      { # of seconds to do rectangles test }
  404.     poly_secs: Word;      { # of seconds to do polygons test }
  405.     arce_secs: Word;      { # of seconds to do arc/ellipse test }
  406.     bitblt_secs: Word;    { # of seconds to do bitblt test }
  407.   text_secs: Word;            { # of seconds to do text test }
  408.   lmem_secs: Word;      { # of seconds to do local memory test }
  409.   gmem_secs: Word;      { # of seconds to do global memory test }
  410.   rfile_io_secs: Word;  { # of seconds to do random file i/o test }
  411.   sfile_io_secs: Word;  { # of seconds to do sequential file i/o test }
  412.  
  413. (**
  414.  ** Following variables are used in the file I/O
  415.  ** tests.
  416.  **)
  417.   sfilesize: LongInt;                                        { Sequential file size }
  418.   sfilereclen: ARRAY [0..3] OF Integer;    { Record lengths }
  419.  
  420. (**
  421.  ** Preference settings.
  422.  **)
  423.   pref_settings: ARRAY[1..max_pref_id] OF Word;
  424.  
  425.     { Following vars. hold stuff for the standard alert }
  426.   {  dialog.  If Count<>0, then x,y holds coordinates at }
  427.   {  which to display the text in AlertDlgText.       }
  428.  
  429. (**
  430.  ** Following vars are used to construct an alert dialog
  431.  ** box...one that just has an "OK" in it.
  432.  ** If ADTCount<>0, then ADTx and ADTy hold coordinates
  433.  ** at which to display the text in AlertDlgText.
  434.  **)
  435.   ADTx, ADTy: Integer;                { Coordinates to display text }
  436.   ADTCount: Integer;                    { Text count }
  437.   AlertDlgText: ARRAY[0..60] of Char;
  438.  
  439.  
  440.   logFileName :String[12];      {Log files are in current directory.}
  441.   autoLogAndExit: Boolean;      {should we automatically write to log file and get out?}
  442.   logFile : Text;
  443.  
  444.   bigFileBuff: ^BigFileBuffType;
  445.   totalRandomIoBytes: LongInt;  {OK, I cheated, it shouldn't be a global.}
  446.   someTests         : Boolean;  { have we ever run any tests? }
  447.  
  448.   CompFileName: ARRAY[0..14] of Char;        { Comparison data file }
  449.   DataFile: Text;                                { File holding text comparison data }
  450.   iscompfilethere: Boolean;            { Set to true if comp file is present }
  451.  
  452.   {**
  453.    ** DisplayBenchLine routines.
  454.    ** Don't physically manipulate these yourself.
  455.    **}
  456.   benchLineHDC:  HDC;
  457.   benchLineX:    Integer;
  458.   benchLineY:    Integer;
  459.   benchLineYInc: Integer;
  460.   benchLineHDCheight:    Integer;
  461.  
  462.   {**
  463.    ** Following globals are used in handling the
  464.    ** benchmark comparison dialog box.
  465.    **}
  466.   bcDispRect:            TRect;            { Display area }
  467.   bcBeginLine:        Integer;        { Beginning line to display }
  468.   bcTotNumLines:    Integer;        { Total # of lines to display }
  469.   bcNumLines:            Integer;        { # of lines in display area }
  470.   bcNumSystems:        Integer;        { # of systems in comparison file }
  471.  
  472.   sysfontheight:    Integer;        { Height of system font }
  473.   ansiffontheight: Integer;        { ANSI fixed font height }
  474.  
  475.   { Following array of handles is used to point to global
  476.     memory blocks where we'll store the data read in from
  477.     the comparison file. }
  478.   fbhand: ARRAY [1..5] of THandle;
  479.  
  480.   { The following pointer leads us to the acutal data stored
  481.     in the blocks referenced by each member of the fbhand[]
  482.     array. }
  483.   fbptr:            PCompData;             { Pointer to comparison data }
  484.  
  485.   oldwinbkcolor: LongInt;             { Save window background color }
  486.  
  487. (******************************
  488.  **   ++ ROUTINES BEGIN ++   **
  489.  ******************************)
  490.  
  491. { ************** }
  492. { TIMER ROUTINES }
  493. { ************** }
  494.  
  495. { ******************** }
  496. {   START STOPWATCH    }
  497. { Starts a stopwatch for benchmarking. }
  498. PROCEDURE StartStopWatch;
  499. BEGIN
  500.     stopwatch:=GetTickCount;
  501. END;
  502.  
  503. { ***************** }
  504. {   STOP STOPWATCH  }
  505. { This procedure turns off the stopwatch, calculates }
  506. { elapsed minutes, seconds, and 1/100 seconds and    }
  507. { places the results in the global stopwatch         }
  508. { variables.                                         }
  509. { Note that this modifies the global  elapsedticks   }
  510. PROCEDURE StopStopWatch;
  511. VAR
  512.     elapsedticks: Longint;
  513.  
  514. BEGIN
  515.     stopwatch:=GetTickCount-stopwatch;
  516. END;
  517.  
  518. (* ****************************************
  519.  ** Accumulate into a timing array memeber
  520.  ** Accumulate the elapsed time into a timing array
  521.  ** entry selected by idx.
  522.  *)
  523. PROCEDURE AccumTiming(idx: Word);
  524. BEGIN
  525.     elapsedtsecarray[idx]:=elapsedtsecarray[idx]+stopwatch;
  526. END;  { AccumTiming }
  527.  
  528. { *************************************** }
  529. { ** RANDOM NUMBER GENERATION ROUTINES ** }
  530. { *************************************** }
  531.  
  532. (* **************************
  533.  ** Generate a random number
  534.  ** Second order linear congruential R.N. generator.
  535.  ** Constants suggested by J.G. Skellam.
  536.  ** If longval==0, returns next number in sequence.
  537.  ** If longval!=0, restarts generator.
  538.  ** NOTE: The generator should be initially started
  539.  ** with a call to Randnum(13);
  540.  **
  541.  *)
  542. FUNCTION Randnum(longval: Longint) : Longint;
  543.  
  544. VAR
  545.     tlong:  Longint;    { Temp storage for long integer }
  546.  
  547. BEGIN
  548.     IF longval<>0 THEN
  549.     BEGIN
  550.         randl[0]:=longval;
  551.         randl[1]:=117;
  552.     END;
  553.  
  554.     tlong:=randl[0]*254754 + randl[1]*529562;
  555.     tlong:=tlong MOD 999563;
  556.     randl[1]:=randl[0];
  557.     randl[0]:=tlong;
  558.  
  559.     Randnum:=tlong;
  560. END;  { Randnum }
  561.  
  562.  
  563. { ********************************************* }
  564. { Get a random number with a specified ceiling. }
  565. FUNCTION GetRandWithCeiling(ceiling: LongInt): LongInt;
  566. BEGIN
  567.   IF ceiling=0 THEN
  568.       BEGIN
  569.         GetRandWithCeiling:=0;
  570.       Exit;
  571.     END;
  572.   GetRandWithCeiling:=Randnum(0) MOD (ceiling+1);
  573.  
  574. END;    { GetRandWithCeiling }
  575.  
  576.  
  577. {********************************************
  578. ** Delay a passed number of seconds.
  579. **}
  580. PROCEDURE DelaySeconds( cnt: Integer );
  581. VAR
  582.   StartTick:  LongInt;
  583.   ThisTick:   LongInt;
  584.   Delay:      LongInt;
  585.  
  586. BEGIN
  587.   StartTick := GetTickCount;
  588.   ThisTick  := GetTickCount;
  589.   Delay     := cnt * 1000;                        { ticks are in milliseconds}
  590.  
  591.   while( Delay > (ThisTick - StartTick) )
  592.   do begin
  593.     ThisTick := GetTickCount;
  594.   END;
  595. END;
  596.  
  597. (**********************************************
  598.  ** Get the system  and ANSI fixed font's height.
  599.  ** A bunch of routines need this for display.
  600.  **)
  601. PROCEDURE GetFontHeight;
  602. VAR
  603.     BWHDC:    Hdc;                                            { Device context }
  604.     fmetrics: tTextMetric;                        { Grab text metrics }
  605. BEGIN
  606.     BWHDC:=GetDC(HByteWin);
  607.   SelectObject(BWHDC,GetStockObject(ANSI_Fixed_Font));
  608.   GetTextMetrics(BWHDC,fmetrics);
  609.   ansiffontheight:=fmetrics.tmHeight;
  610.   SelectObject(BWHDC,GetStockObject(System_Font));
  611.   GetTextMetrics(BWHDC,fmetrics);
  612.   sysfontheight:=fmetrics.tmHeight;
  613.   ReleaseDC(HByteWin,BWHDC);
  614. END;    { GetSysFontHeight }
  615.  
  616.  
  617. (*
  618.  ** Erase the client area
  619.  *)
  620. PROCEDURE EraseClient;
  621. VAR
  622.     xmin, xmax: Integer;              { X clipping bounds }
  623.     ymin, ymax: Integer;              { Y clipping bounds }
  624.   HisRect: TRect;                                        { Client rectangle }
  625.     HDevCont: HDC;                    { Device context }
  626. BEGIN
  627.     { Get a device context for the window }
  628.     HDevCont:=GetDC(HByteWin);
  629.   { Black brush, null pen }
  630.   SelectObject(HdevCont,GetStockObject(Black_Brush));
  631.   SelectObject(HdevCont,GetStockObject(Black_Pen));
  632.  
  633.   { Get the rectangle coordinates }
  634.   GetClientRect(HByteWin,HisRect);
  635.     xmin:=HisRect.left;
  636.     ymin:=HisRect.top;
  637.     xmax:=HisRect.right;
  638.     ymax:=HisRect.bottom;
  639.   { Paint the rectangle }
  640.   Rectangle(HdevCont,xmin,ymin,xmax,ymax);
  641.  
  642.   { Release the context }
  643.     ReleaseDC(HBytewin, HDevCont);
  644. END;
  645.  
  646. {********************************************
  647.  **  Initialize the display variables.
  648.  **}
  649. PROCEDURE InitBenchDisplay;
  650. var
  651.   fmetrics: TTextMetric;                { For grabbing font metrics }
  652. begin
  653.   BenchLineHDC := GetDC( HByteWin );
  654.   BenchLineX   := 10;
  655.  
  656.   { Set us up with the system font }
  657.   SelectObject( BenchLineHDC, GetStockObject(System_Font) );
  658.  
  659.   { Determine starting coordinates }
  660.   GetTextMetrics( BenchLineHDC, fmetrics );
  661.  
  662. {  BenchLineY := fmetrics.tmHeight;
  663.   BenchLineYInc := BenchLineY; }
  664.  
  665.   BenchLineY := sysfontheight;
  666.   BenchLineYInc:= sysfontheight;
  667.  
  668.   { Clear the client window }
  669.   EraseClient;
  670.  
  671.   { Set foreground and background colors }
  672.   SetTextColor( BenchLineHDC, RGB(255,255,255) );
  673.   SetBkColor( BenchLineHDC, RGB(0,0,0) );
  674.   SetBkMode( BenchLineHDC, Opaque );
  675.  
  676.  
  677. end;
  678.  
  679. PROCEDURE CloseBenchDisplay;
  680. begin
  681.   { Release the display context }
  682.   ReleaseDC(HByteWin, BenchLineHDC );
  683. end;
  684.  
  685.  
  686. (********************************************
  687. ** Display a single line of benchmark results
  688. *********************************************
  689. ** Pass this function the string to be displayed and the
  690. ** initial coordinates.  It returns the height of the
  691. ** string, which can be used to position the next string
  692. ** in sequence.
  693. ** Note, I'm using globals all over the place which is rather messy.
  694. **       Still, its a lot cleaner than displaying each time.
  695. **       Definitely needs a rethink.
  696. *)
  697. FUNCTION DisplayBenchLine( hisstring: PChar; hisstringlen: Integer): Integer;
  698. VAR
  699.     tlong: Longint;                { Temp long integer }
  700. BEGIN
  701.   if( BenchLineHDC <> 0 )      { ensure we've setup an HDC }
  702.   then begin
  703.       TextOut(BenchLineHDC, BenchLineX, BenchLineY, hisstring, hisstringlen);
  704.     tlong := GetTextExtent(BenchLineHDC, hisstring, hisstringlen );
  705.     DisplayBenchLine := WordRec(tlong).hi;
  706.     BenchLineY := BenchLineY + WordRec(tlong).hi;
  707.   end;
  708. END;    { DisplayBenchLine }
  709.  
  710.  
  711. { *************************************** }
  712. {     WINDOWS INITIALIZATION ROUTINES     }
  713. { *************************************** }
  714.  
  715.  
  716. PROCEDURE setParm( parmString: String );
  717. BEGIN
  718.   if( '-L' = parmString )
  719.   then begin
  720.     autoLogAndExit := TRUE;
  721.   end;
  722.  
  723.   if( not (Pos( '-', parmString ) = 1) )
  724.   then begin
  725.     { not a flag -- must be the name of the log file.
  726.     { note: we're not checking for validity here. but we do ensure proper length.}
  727.     logFileName := Copy( parmString, 1, 12 );
  728.   end;
  729. END;  {setParm }
  730.  
  731.  
  732. { *********************************** }
  733. { Initialize any parameters from the command line. }
  734. PROCEDURE InitCommandLineParameters;
  735. VAR
  736.     i: Integer;           { Loop index }
  737.   lastParm : Integer;   { number of parameters on command line }
  738.   parmString : String;  { a particular command line parameters }
  739. BEGIN
  740.   lastParm := Paramcount;
  741.  
  742.   if( lastParm > 0 )
  743.   THEN BEGIN
  744.     for i:= 1 to lastParm 
  745.     do BEGIN
  746.       parmString := ParamStr( i );
  747.       setParm( parmString );
  748.     END;
  749.   END;
  750.  
  751. END;
  752.  
  753.  
  754. { *********************************** }
  755. { Initialize all the global variables }
  756. PROCEDURE InitGlobals;
  757. VAR
  758.     i: Integer;                                             { Loop index }
  759.   fpath: ARRAY[0..fsPathName] of CHAR;    { File path }
  760. BEGIN
  761.  
  762.     { Set times to their defaults }
  763.     pixel_secs:=min_pixel_secs;
  764.     line_secs:=min_line_secs;
  765.     rect_secs:=min_rect_secs;
  766.     poly_secs:=min_poly_secs;
  767.     arce_secs:=min_arce_secs;
  768.     bitblt_secs:=min_bitblt_secs;
  769.   text_secs:=min_text_secs;
  770.   lmem_secs := min_lmem_secs;
  771.   gmem_secs := min_gmem_secs;
  772.   rfile_io_secs := min_rfile_io_secs;     {current interface does not use this, code does}
  773.   sfile_io_secs := min_sfile_io_secs;     {current interface/code does not use this }
  774.  
  775.   { Set other defaults }
  776.   sfilesize:=5000000;        { Seq. file is 5 million characters }
  777.   sfilereclen[0]:=256;        { Seq. file record lengths }
  778.   sfilereclen[1]:=512;
  779.   sfilereclen[2]:=1024;
  780.   sfilereclen[3]:=4096;
  781.  
  782.     { Check all the checkboxes }
  783.     FOR i:=1 TO max_test_id DO
  784.         do_test_flags[i]:=TRUE;
  785.  
  786.     { Initialize the random number generator }
  787.     Randnum(13);
  788.  
  789.   { Initialize the log file. }
  790.   LogFileName := DefLogName;
  791.   autoLogAndExit := FALSE;
  792.  
  793.   InitCommandLineParameters;
  794.  
  795.   someTests := FALSE;           { no tests have yet been run }
  796.  
  797.   { Search for the comparison data file.  Set appropriate
  798.     flag depending on whether or the file is present or not. }
  799.   StrPCopy(CompFileName,DefCompName);
  800.   FileSearch(fpath,CompFileName,'');
  801.   IF fpath[0]=#0 THEN
  802.       iscompfilethere:=FALSE
  803.   ELSE
  804.       BEGIN
  805.           iscompfilethere:=TRUE;
  806.           Assign(DataFile,CompFileName);
  807.     END;
  808.  
  809.   { Get the height of the system font }
  810.   GetFontHeight;
  811.  
  812.   { Initialize the benchdisplayline variables. }
  813.   benchLineX   := 0;
  814.   benchLineY   := 0;
  815.   benchLineYInc:= 0;
  816.   benchLineHDC := 0;
  817.  
  818. END;  { InitGlobals }
  819.  
  820.  
  821. { ********************************** }
  822. { ** DIALOG BOX HANDLING ROUTINES ** }
  823. { ********************************** }
  824.  
  825. (* ****************************************
  826.  ** Given a button id, return the test id.
  827.  *)
  828. FUNCTION ButtonToTestID(buttonid: Word) : Word;
  829. VAR
  830.     i: Word;          { Index variable }
  831. BEGIN
  832.     ButtonToTestID:=0;
  833.  
  834.     (* Step through the button_ids[] array looking
  835.     ** for a match.  Exit with index value when
  836.     ** you find one.
  837.     *)
  838.     FOR i:=1 TO max_test_id DO
  839.         IF button_ids[i]=buttonid THEN
  840.             BEGIN
  841.                 ButtonToTestID:=i;
  842.                 Exit;
  843.             END;
  844.  
  845. END;  { ButtonToTestID }
  846.  
  847. (* *******************************************
  848.  ** Save benchmark configuration settings in
  849.  ** temporary storage.  Call this routine
  850.  ** when the configuration dialog box is first
  851.  ** opened.  This lets the system restore the
  852.  ** initial setting if a CANCEL is hit.
  853.  *)
  854. PROCEDURE SaveConfigToTemp;
  855. VAR
  856.     i: Integer;       { Index variable }
  857. BEGIN
  858.  
  859.     FOR i:=1 TO max_test_id DO
  860.         tdo_test_flags[i]:=do_test_flags[i];
  861.  
  862. END;  { SaveConfigToTemp }
  863.  
  864. (* ********************************************
  865.  ** Restore benchmark configuration settings
  866.  ** from temporary storage.  Call this routine
  867.  ** if a CANCEL button is hit.
  868.  *)
  869. PROCEDURE RestoreConfigFromTemp;
  870. VAR
  871.     i: Integer;       { Integer variable }
  872. BEGIN
  873.  
  874.     FOR i:=1 TO max_test_id DO
  875.         do_test_flags[i]:=tdo_test_flags[i];
  876.  
  877. END;  { RestoreConfigFromTemp }
  878.  
  879. { ************************************************ }
  880. { Verify that defaults selected are within bounds. }
  881. { This function examines the selected defaults and }
  882. { returns 0 if they're all ok.  Otherwise, it      }
  883. { returns the ID+1 of the first editbox that holds }
  884. { disallowed values.                               }
  885. FUNCTION CheckInBounds(HDialog : HWnd): Word;
  886. VAR
  887.  i: Word;             { Used as index }
  888.  secs: Integer;       { Seconds }
  889.  transflag: Bool;     { Translation flag }
  890. BEGIN
  891.     FOR i:= 0 TO 7 DO
  892.     BEGIN
  893.             secs:=GetDlgItemInt(HDialog,edit_box_ids[i],
  894.                             @transflag, TRUE);
  895.             IF (transflag=FALSE) OR (secs<edit_box_mins[i])
  896.             THEN
  897.                 BEGIN
  898.                     CheckInBounds:=i+1;
  899.                     Exit;
  900.                 END;
  901.     END;  { FOR loop }
  902.     CheckInBounds:=0;
  903. END;    { CheckInBounds }
  904.  
  905.  
  906. { ******************************************************* }
  907. { Load the settings of the benchmark configuration dialog }
  908. { box into the proper global variables.  By the time      }
  909. { this routine is called, we've verified that all the     }
  910. { entered numbers are legit.                              }
  911. PROCEDURE GetBenchConfigSettings( HDialog : HWnd);
  912. VAR
  913.     i: Word;            { Used as index }
  914.     secs: Integer;      { Seconds }
  915.     transflag: Bool;    { Translation flag }
  916.  
  917. BEGIN
  918.  
  919.     { First get all the edit box contents }
  920.     pixel_secs:=GetDlgItemInt(HDialog,ID_PIXEL_SECS,
  921.                             @transflag, TRUE);
  922.  
  923.     line_secs:=GetDlgItemInt(HDialog,ID_LINE_SECS,
  924.                             @transflag, TRUE);
  925.  
  926.     rect_secs:=GetDlgItemInt(HDialog,ID_RECT_SECS,
  927.                             @transflag, TRUE);
  928.  
  929.     poly_secs:=GetDlgItemInt(HDialog,ID_POLY_SECS,
  930.                             @transflag, TRUE);
  931.  
  932.     arce_secs:=GetDlgItemInt(HDialog,ID_ARCE_SECS,
  933.                             @transflag, TRUE);
  934.  
  935.     bitblt_secs:=GetDlgItemInt(HDialog,ID_BITBLT_SECS,
  936.                             @transflag, TRUE);
  937.  
  938.   text_secs:=GetDlgItemInt(HDialog,ID_TEXT_SECS,
  939.                           @transflag, TRUE);
  940.  
  941. END;    { GetBenchConfigSettings }
  942.  
  943. (* *********************************
  944.  ** Handle a standard alert dialog.
  945.  ** We'll define a "standard alert dialog" to be a dialog
  946.  ** box that informs the user of some outstanding condition.
  947.  ** The only thing the user can do is hit the OK button.
  948.  *)
  949. FUNCTION StandardAlertDialog(Dialog: HWnd; Message, WParam: Word;
  950.      LParam: LongInt): Bool; export;
  951. VAR
  952.     DlgDC:    HDC;            { Context for dialog }
  953.     HMDevCont: HDC;        { Memory context }
  954.   bithand: HBitmap;    { Handle for bitmap }
  955.  
  956. BEGIN
  957.     CASE Message OF
  958.         wm_InitDialog:
  959.             BEGIN
  960.           IF ADTCount>0 THEN
  961.            SetDlgItemText(Dialog, IDL_Logfield, AlertDlgText);
  962.                                   { Set the focus }
  963.                  SetFocus(GetDlgItem(Dialog,IDB_OK));
  964.                 StandardAlertDialog:=FALSE;
  965.                 EXIT;
  966.             END;
  967.  
  968.     wm_Paint:
  969.         BEGIN
  970.           IF ADTCount<0 THEN
  971.              { A negative ADTCount is a sneaky way of telling us
  972.             to display the BYTE Logo. }
  973.             BEGIN
  974.               DlgDC:=GetDC(Dialog);
  975.             bithand:=LoadBitMap(HInstance,'BYTELOGO');
  976.             HMDevCont:=CreateCompatibleDC(DlgDC);
  977.             SelectObject(HMDevCont,bithand);
  978.             BitBlt(DlgDC,125,10,200,68,HMDevCont,0,0,SrcCopy);
  979.             DeleteDC(HMDevCont);
  980.             ReleaseDC(Dialog,DlgDC);
  981.             DeleteObject(bithand);
  982.           END;
  983.         StandardAlertDialog:=FALSE;
  984.       END;
  985.  
  986.         wm_Command:
  987.             CASE WParam OF
  988.                 IDB_OK:
  989.                     BEGIN
  990.                         EndDialog(Dialog,0);
  991.                         StandardAlertDialog:=TRUE;
  992.               ADTCount:=0;        { Don't need string }
  993.                         EXIT;
  994.                     END;
  995.             END;  { CASE WParam }
  996.     END;    { CASE Message }
  997.     StandardAlertDialog:=FALSE;
  998. END;  { StandardAlertDialog }
  999.  
  1000.  
  1001. FUNCTION getLogNameDialogAction( Dialog: HWnd; Message, WParam: Word;
  1002.                                  LParam: LongInt ): Bool; export;
  1003. VAR
  1004.     DlgDC:    HDC;            { Context for dialog }
  1005.   theName: ARRAY [0..14] of CHAR;
  1006.   strName: String[13];
  1007.  
  1008. BEGIN
  1009.     CASE Message OF
  1010.         wm_InitDialog:
  1011.             BEGIN
  1012.         StrPCopy( theName, logfileName );
  1013.         SetDlgItemText(Dialog, IDL_Logfield, theName );
  1014.                  { Set the focus }
  1015.                  SetFocus(GetDlgItem(Dialog,IDL_logfield));
  1016.                 getLogNameDialogAction:=FALSE;
  1017.                 EXIT;
  1018.             END;
  1019.  
  1020.         wm_Command:
  1021.             CASE WParam OF
  1022.                 IDL_OK:       {grab the new logfile -- eventually do error checking }
  1023.                     BEGIN
  1024.                         EndDialog(Dialog,0);
  1025.                         getLogNameDialogAction:=TRUE;
  1026.             GetDlgItemText( Dialog, IDL_LogField, theName, 13);
  1027.             strName := StrPas( theName );
  1028.             { do error checking here -- if ok, then ...}
  1029.             logFileName := strName;
  1030.                         EXIT;
  1031.                     END;
  1032.         IDL_CANCEL: {don't change the logfile name}
  1033.           BEGIN
  1034.             EndDialog( Dialog, 0 );
  1035.             getLogNameDialogAction := TRUE;
  1036.             EXIT;
  1037.           END;
  1038.             END;  { CASE WParam }
  1039.     END;    { CASE Message }
  1040.     getLogNameDialogAction:=FALSE;
  1041. END;
  1042.  
  1043.  
  1044. { ************************************* }
  1045. { Handle the set-to-defaults dialog box }
  1046. { This dialog box simply accepts a yes/no response. }
  1047. { Yes sets benchmark configurations to their }
  1048. { defaults...no leaves them unchanged. }
  1049. FUNCTION SetToDefaultsDialog(Dialog: HWnd; Message, WParam: Word;
  1050.     LParam: LongInt): Bool; export;
  1051.  
  1052. BEGIN
  1053.     CASE Message OF
  1054.         wm_InitDialog:
  1055.             BEGIN 
  1056.  
  1057.                 { Set the focus }
  1058.                 SetFocus(GetDlgItem(Dialog,IDB_OK));
  1059.                 SetToDefaultsDialog:=FALSE;
  1060.                 EXIT;
  1061.             END;
  1062.  
  1063.         wm_Command:
  1064.             BEGIN
  1065.                 CASE WParam OF
  1066.  
  1067.                     IDB_OK:
  1068.                         BEGIN
  1069.                             { Set all items to default }
  1070.                             EndDialog(Dialog,0);
  1071.                             SetToDefaultsDialog:=TRUE;
  1072.                             EXIT;
  1073.                         END;
  1074.                     IDB_CANCEL:
  1075.               BEGIN
  1076.                             EndDialog(Dialog,0);
  1077.                             SetToDefaultsDialog:=TRUE;
  1078.                             EXIT;
  1079.             END;
  1080.                 END;  { CASE WParam }
  1081.             END;    { BEGIN }
  1082.     END;        { CASE Message }
  1083.  
  1084.     SetToDefaultsDialog:=FALSE;
  1085. END;          { SetToDefaultsDialog }
  1086.  
  1087. (* **********************
  1088.  ** Flip a dialog button
  1089.  ** This routine flips the state of a dialog button.
  1090.  *)
  1091. FUNCTION FlipButton(Dialog: HWnd; button_id: Integer;
  1092.     curr_state : Bool) : Bool;
  1093.  
  1094. BEGIN
  1095.  
  1096.     IF curr_state=TRUE THEN
  1097.         BEGIN
  1098.             CheckDlgButton(Dialog,button_id,0);
  1099.             FlipButton:=FALSE;
  1100.         END
  1101.     ELSE
  1102.         BEGIN
  1103.             CheckDlgButton(Dialog,button_id,1);
  1104.             FlipButton:=TRUE;
  1105.         END;
  1106.  
  1107. END;  { FlipButton }
  1108.  
  1109.  
  1110. { ********************************************* }
  1111. { Handle the benchmark configuration dialog box }
  1112. { This is the big, nasty dialog box that gets   }
  1113. {  benchmark configuration settings.  We grab   }
  1114. {  stuff into a temporary area when we get an   }
  1115. {  init dialog message.  If the use hits an ok, }
  1116. {  we copy the temporary area into the real     }
  1117. {  variables...if the user hits cancel, we dump }
  1118. {  the temporary stuff and keep the real        }
  1119. {  variables unchanged.                                                 }
  1120. FUNCTION BenchConfigDialog(Dialog: HWnd; Message, WParam: Word;
  1121.     LParam: LongInt): Bool; export;
  1122.  
  1123. VAR
  1124.     test_id: Word;      { Test Identification number }
  1125.   i: Integer;                    { Index value }
  1126. BEGIN
  1127.     BenchConfigDialog:=True;
  1128.     CASE Message OF
  1129.         wm_InitDialog:    { ** INITIALIZE DIALOG BOX ** }
  1130.             BEGIN
  1131.                 { Copy current into temporary variables }
  1132.                 SaveConfigToTemp;
  1133.  
  1134.         { Set buttons based on current values }
  1135.         FOR i:=1 TO max_test_id DO
  1136.             IF do_test_flags[i] THEN
  1137.                 CheckDlgButton(Dialog,button_ids[i],1)
  1138.           ELSE
  1139.               CheckDlgButton(Dialog,button_ids[i],0);
  1140.  
  1141.         { Set edit boxes based on current values }
  1142.               SetDlgItemInt(Dialog,ID_PIXEL_SECS,pixel_secs, TRUE);
  1143.                 SetDlgItemInt(Dialog,ID_LINE_SECS,line_secs, TRUE);
  1144.                 SetDlgItemInt(Dialog,ID_RECT_SECS,rect_secs, TRUE);
  1145.                 SetDlgItemInt(Dialog,ID_POLY_SECS,poly_secs, TRUE);
  1146.                 SetDlgItemInt(Dialog,ID_ARCE_SECS,arce_secs, TRUE);
  1147.                 SetDlgItemInt(Dialog,ID_BITBLT_SECS,bitblt_secs, TRUE);
  1148.         SetDlgItemInt(Dialog,ID_TEXT_SECS,text_secs,TRUE);
  1149.  
  1150.                 { Set the focus }
  1151.                 SetFocus(GetDlgItem(Dialog,IDB_OK));
  1152.                 BenchConfigDialog:=FALSE;
  1153.                 EXIT;
  1154.             END;
  1155.  
  1156.         wm_Command:       { ** HANDLE COMMAND ACTION ** }
  1157.             CASE WParam OF
  1158.  
  1159.                 IDB_OK:          { ** OK Button ** }
  1160.                     BEGIN
  1161.  
  1162.                         (* Make sure all the settings make sense and
  1163.                         ** are within bounds.  If not, throw up an
  1164.                         ** alert dialog and keep things as they
  1165.                         ** are.  If so, read the benchmark configurations
  1166.                         ** to make them current and get rid of the
  1167.                         ** dialog box.
  1168.                         *)
  1169.                         IF CheckInBounds(Dialog)<> 0 THEN
  1170.                             BEGIN
  1171.                                 (* Throw up alert *)
  1172.                 MessageBeep(0);
  1173.                             END
  1174.                         ELSE
  1175.                             BEGIN
  1176.                                 (* All is well *)
  1177.                                 GetBenchConfigSettings(Dialog);
  1178.                             END;
  1179.                         EndDialog(Dialog,NULL);
  1180.                         BenchConfigDialog:=TRUE;
  1181.                         EXIT;
  1182.                     END;
  1183.  
  1184.                 IDB_CANCEL:      { ** Cancel button ** }
  1185.                     BEGIN
  1186.  
  1187.                         (* Set everything back to the way it
  1188.                         ** was before the dialog box was
  1189.                         ** opened.  Then shut down.
  1190.                         *)
  1191.                         RestoreConfigFromTemp;
  1192.                         EndDialog(Dialog,NULL);
  1193.                         BenchConfigDialog:=TRUE;
  1194.                         EXIT;
  1195.                     END;
  1196.  
  1197.                 ID_PIXEL_BUTTON,    { ** Pixel test button ** }
  1198.                 ID_LINES_BUTTON,    { ** Lines test button ** }
  1199.                 ID_RECTS_BUTTON,    { ** Rectangles test button ** }
  1200.                 ID_POLYS_BUTTON,    { ** Polygons test button ** }
  1201.                 ID_ARCE_BUTTON,     { ** Arc/ellipse test button ** }
  1202.                 ID_BITBLT_BUTTON,   { ** BitBlt test button ** }
  1203.                 ID_LMEM_BUTTON,     { ** Local memory test button ** }
  1204.                 ID_GMEM_BUTTON,     { ** Global memory test button ** }
  1205.                 ID_SFIO_BUTTON,     { ** Seq. file i/o test button ** }
  1206.                 ID_RFIO_BUTTON,     { ** Rand. file i/o test button ** }
  1207.                 ID_TEXT_BUTTON:     { ** Text test button ** }
  1208.                     BEGIN
  1209.                         test_id:=ButtonToTestID(WParam);
  1210.                         do_test_flags[test_id]:=FlipButton(Dialog,WParam,
  1211.                                                                     do_test_flags[test_id]);
  1212.                         BenchConfigDialog:=TRUE;
  1213.                         EXIT;
  1214.                     END;
  1215.  
  1216.                 ELSE
  1217.                     BEGIN
  1218.                         BenchConfigDialog:=FALSE;
  1219.                         EXIT;
  1220.                     END;
  1221.             END;    { CASE WParam }
  1222.  
  1223.         ELSE
  1224.             BEGIN
  1225.                 BenchConfigDialog:=FALSE;
  1226.                 EXIT;
  1227.             END;
  1228.  
  1229.     END;        { CASE Message }
  1230. END;    { BenchConfigDialog }
  1231.  
  1232. (**********************************
  1233. ** DEVICE CONFIGURATION ROUTINES **
  1234. **********************************)
  1235.  
  1236. (****************************************
  1237. ** Show the current system configuration.
  1238. ** This routine displays stuff like
  1239. ** processor/coprocessor type, screen size, etc.
  1240. *)
  1241. PROCEDURE ShowDevConfig;
  1242. BEGIN
  1243.  
  1244.     { Call assembly routine to determine processor and }
  1245.   {  coprocessor type/presence.                      }
  1246.  
  1247.   { Call GetDeviceCaps for screen info. }
  1248.  
  1249.   { Clear the display area }
  1250.  
  1251.   { Display the information and return }
  1252. END;    { ShowDevConfig }
  1253.  
  1254.  
  1255.  
  1256. { ************************************ }
  1257. { ** BENCHMARK ROUTINES THEMSELVES! ** }
  1258. { ************************************ }
  1259. FUNCTION LMin(a,b: Integer): Longint;
  1260. BEGIN
  1261.     IF a<b THEN LMin:=a ELSE LMin:=b;
  1262. END;
  1263.  
  1264. (*************************
  1265.  ** Local Memory benchmark
  1266.  ** This procedure executes the local memory test.
  1267.  *)
  1268. PROCEDURE LMemTest;
  1269.  
  1270. VAR
  1271.     i: Integer;                 { Array index }
  1272.     numreqs: Word;              { # of requests }
  1273.     locsize: Word;                { Size of local memory in bytes }
  1274.     memhandles: ARRAY[0..1000] OF THandle;  { Memory handles }
  1275.     reqsizes: ARRAY[0..1000] OF LongInt;    { Request sizes }
  1276.     totrequest: LongInt;        { Total request }
  1277.     memflags1: Word;            { Flags for requests }
  1278.     memflags2: Word;            { Flags for requests }
  1279.     tmemptr: Pointer;           { Temp. for holding pointer }
  1280.     dlgproc: TFarProc;          { Procedure instance }
  1281.   reqsize: LongInt;                        { Total request size }
  1282.   tstring: Array[0..8] of Char;     { Temp string for conversion }
  1283.   temphand: THandle;                    { Temp handle }
  1284.   outstr:  Array [0..80] of Char; { message to display }
  1285.   outstrlen: Integer;             { need to know how long it is }
  1286. BEGIN
  1287.  
  1288.     InitBenchDisplay;
  1289.  
  1290.   strPCopy( @outstr, 'Running local memory test.');
  1291.   outstrlen := StrLen( @outstr );
  1292.   DisplayBenchLine( @outstr, outstrlen );
  1293.   
  1294.  
  1295.     { Clear the timer array }
  1296.     elapsedtsecarray[lmem_test_id]:=0;
  1297.   iterarray[lmem_test_id]:=0;
  1298.  
  1299.     { ** LOCAL MEMORY TEST ** }
  1300.     
  1301.     { Determine amount of local memory with call... }
  1302.     { ... to LocalCompact().  If this is less than  }
  1303.     {  32K, then we've got a problem.               }
  1304.     locsize:=LocalCompact(max_local_memsize);
  1305.     IF locsize<31000 THEN
  1306.     BEGIN
  1307.         (* Handle problem of < 32K of local memory.  This should
  1308.         ** throw up a dialog box that says "Not enough memory for
  1309.         ** local test." With just an OK.  After the user clicks
  1310.         ** the OK, the dialog box goes away and this function
  1311.         ** exits.
  1312.         *)
  1313.     ADTx:=28;                        { Display current memory in dialog }
  1314.     ADTy:=30;
  1315.     Str(locsize DIV 1024,tstring);
  1316.     StrCopy(@AlertDlgText,'(');
  1317.     StrCat(@AlertDlgText,@tstring);
  1318.     StrCat(@AlertDlgText,'K Free)');
  1319.     ADTCount:=StrLen(@AlertDlgText);
  1320.         dlgproc:=MakeProcInstance(@StandardAlertDialog,HInstance);
  1321.         DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
  1322.         FreeProcInstance(dlgproc);
  1323.         Exit;
  1324.     END;
  1325.  
  1326.  
  1327.     { Generate a random array of memory requests. }
  1328.     {  Each request is no less than 32 bytes and  }
  1329.     {  no greater than  512 bytes.  Furthermore,  }
  1330.     {  the sum of all requests will not exceed    }
  1331.     {  a specified amount.                        }
  1332.     numreqs:=0;
  1333.     totrequest:=0;
  1334.     REPEAT
  1335.     BEGIN
  1336.         reqsize:=ABS(GetRandWithCeiling(480))+32;
  1337.         reqsizes[numreqs]:=reqsize;
  1338.         Inc(numreqs);
  1339.         totrequest:=totrequest+reqsize;
  1340.   END
  1341.     UNTIL (numreqs=max_local_memitems) OR (totrequest>max_local_memsize);
  1342.  
  1343.     { Set up the flags word for upcoming requests }
  1344.     memflags1:=lmem_Moveable OR lmem_ZeroInit;
  1345.  
  1346.     memflags2:=lmem_Moveable;
  1347.  
  1348.   locsize:=0;
  1349.  
  1350.  
  1351.     { Enter timing loop }
  1352.     WHILE (elapsedtsecarray[lmem_test_id] DIV 1000)<lmem_secs  DO
  1353.     BEGIN
  1354.  
  1355.     { Start timing }
  1356.     StartStopwatch;
  1357.  
  1358.       { Step through the array, calling LocalAlloc().   }
  1359.       { Blocks are moveable and memory is not discarded }
  1360.       {  or compacted.  Also, memory is initialized.    }
  1361.       FOR i:=0 TO numreqs-1 DO
  1362.           memhandles[i]:=LocalAlloc(memflags1, WordRec(reqsizes[i]).lo);
  1363.  
  1364.       { Step through the array and lock every other block. }
  1365.       FOR i:=0 TO ((numreqs-1) DIV 2) DO
  1366.           tmemptr:=LocalLock(memhandles[i+i]);
  1367.  
  1368.       { Call LocalCompact() with nonzero argument }
  1369.       LocalCompact(8000);
  1370.  
  1371.       { Step through array, unlocking and freeing blocks }
  1372.       {  locked in previous step.  Add amount freed to   }
  1373.       {  localsize variable.                             }
  1374.       { NOTE: LATER VERSIONS SHOULD PUT CHECK ON THE     }
  1375.       {  LOCALFREE() CALL TO VERIFY THAT IT EXECUTED     }
  1376.       {  PROPERLY.                                       }
  1377.       FOR i:=0 TO ((numreqs-1) DIV 2) DO
  1378.       BEGIN
  1379.           LocalUnlock(memhandles[i+i]);
  1380.           locsize:=locsize+reqsizes[i+i];
  1381.           LocalFree(memhandles[i+i]);
  1382.       END;
  1383.  
  1384.       { Go through the array of remaining blocks, issuing }
  1385.       {  a LocalReAlloc on those blocks, expanding each   }
  1386.       {  so that it consumes remaining memory.  Then free }
  1387.       {  that block and go on to the next.                }
  1388.     { NOTE: CHECK THIS LOOP!!! ARE THE PARAMS OK???     }
  1389.       FOR i:=0 TO ((numreqs-2) DIV 2) DO
  1390.       BEGIN
  1391.           temphand:=
  1392.           LocalRealloc(memhandles[i+i+1],reqsizes[i+i+1]+locsize,memflags2);
  1393.       IF temphand<>0 THEN memhandles[i+i+1]:=temphand;
  1394.           LocalFree(memhandles[i+i+1]);
  1395.           locsize:=locsize+reqsizes[i+i+1];
  1396.       END;
  1397.  
  1398.       { Stop timing and record results }
  1399.       StopStopWatch;
  1400.  
  1401.       { Increment iterations and accumulate seconds }
  1402.         Inc(iterarray[lmem_test_id]); 
  1403.          AccumTiming(lmem_test_id);
  1404.  
  1405.      END;  { While }
  1406.  
  1407. END;  { LmemTest }
  1408.  
  1409. (*********************
  1410.  ** Global memory test
  1411.  ** This procedure executes the global memory test.
  1412.  *)
  1413. PROCEDURE GMemTest;
  1414.  
  1415. VAR
  1416.     i: Integer;                 { Array index }
  1417.     numreqs: Word;              { # of requests }
  1418.     memhandles: ARRAY[0..1000] OF THandle;  { Memory handles }
  1419.     reqsizes: ARRAY[0..1000] OF LongInt;    { Request sizes }
  1420.     totrequest: LongInt;        { Total request }
  1421.     memflags1: Word;            { Flags for requests }
  1422.     memflags2: Word;            { Flags for requests }
  1423.     tmemptr: Pointer;           { Temp. for holding pointer }
  1424.     globsize: LongInt;            { Size of largest global block }
  1425.     dlgproc: TFarProc;          { Procedure instance }
  1426.   reqsize: LongInt;                        { Max request size }
  1427.   tstring: Array[0..8] of Char;     { Temp string for conversion }
  1428.   temphand: THandle;                    { Temporary handle }
  1429.   outstr:  Array [0..80] of Char; { message to display }
  1430.   outstrlen: Integer;             { need to know how long it is }
  1431.  
  1432. BEGIN
  1433.  
  1434.     InitBenchDisplay;
  1435.  
  1436.   strPCopy( @outstr, 'Running global memory test.');
  1437.   outstrlen := StrLen( @outstr );
  1438.   DisplayBenchLine( @outstr, outstrlen );
  1439.   
  1440.     { Clear timing }
  1441.   elapsedtsecarray[gmem_test_id]:=0;
  1442.   iterarray[gmem_test_id]:=0;
  1443.  
  1444.     { Determine amount of Global memory with call... }
  1445.     { ... to GlobalCompact().  If this is less than  }
  1446.     {  1024K, then we've got a problem.              }
  1447.     globsize:=GlobalCompact(1050000);
  1448.   globsize:=GetFreeSpace(0);
  1449.     IF globsize<1048576 THEN
  1450.     BEGIN
  1451.         (* Handle problem of < 1M of global memory.  This should
  1452.         ** throw up a dialog box that says "Not enough memory for
  1453.         ** global test." With just an OK.  After the user clicks
  1454.         ** the OK, the dialog box goes away and this function
  1455.         ** exits.
  1456.         *)
  1457.     ADTx:=28;                        { Display current memory in dialog }
  1458.     ADTy:=30;
  1459.     Str(globsize DIV 1024,tstring);
  1460.     StrCopy(@AlertDlgText,'(');
  1461.     StrCat(@AlertDlgText,@tstring);
  1462.     StrCat(@AlertDlgText,'K Free)');
  1463.     ADTCount:=StrLen(@AlertDlgText);
  1464.  
  1465.         dlgproc:=MakeProcInstance(@StandardAlertDialog,HInstance);
  1466.         DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
  1467.         FreeProcInstance(dlgproc);
  1468.         Exit;
  1469.     END;
  1470.  
  1471.  
  1472.     { Generate a random array of memory requests.  }
  1473.     {  Each request is no less than 512 bytes and  }
  1474.     {  no greater than 4K bytes.  Furthermore,     }
  1475.     {  the sum of all requests will not exceed     }
  1476.     {  a specified amount.                         }
  1477.     numreqs:=0;
  1478.     totrequest:=0;
  1479.     REPEAT
  1480.     BEGIN
  1481.         reqsize:=ABS(GetRandWithCeiling(3584))+512;
  1482.         reqsizes[numreqs]:=reqsize;
  1483.         Inc(numreqs);
  1484.         totrequest:=totrequest+reqsize;
  1485.   END
  1486.     UNTIL (numreqs=max_global_memitems) OR (totrequest>max_global_memsize);
  1487.  
  1488.     { Set up the flags words for upcoming requests }
  1489.     memflags1:=gmem_Moveable OR gmem_ZeroInit;
  1490.     memflags2:=gmem_Moveable;
  1491.   globsize:=0;
  1492.  
  1493.  
  1494.     { Enter timing loop }
  1495.     WHILE (elapsedtsecarray[gmem_test_id] DIV 1000)<gmem_secs  DO
  1496.     BEGIN
  1497.       { Start timing }
  1498.       StartStopwatch;
  1499.  
  1500.       { Step through the array, calling GlobalAlloc().  }
  1501.       { Blocks are moveable and memory is not discarded }
  1502.       {  or compacted.  Also, memory is initialized.    }
  1503.       FOR i:=0 TO numreqs-1 DO
  1504.         BEGIN
  1505.           memhandles[i]:=GlobalAlloc(memflags1, reqsizes[i]);
  1506.       IF memhandles[i]=0 THEN MessageBeep(0);
  1507.       END;
  1508.  
  1509.       { Step through the array and lock every other block. }
  1510.       FOR i:=0 TO ((numreqs-1) DIV 2) DO
  1511.           tmemptr:=GlobalLock(memhandles[i+i]);
  1512.  
  1513.       { Call GlobalCompact() with nonzero argument }
  1514.       GlobalCompact(1000);
  1515.  
  1516.       { Step through array, unlocking and freeing blocks }
  1517.       {  locked in previous step.  Add amount freed to   }
  1518.       {  globalsize variable.                            }
  1519.       { NOTE: LATER VERSIONS SHOULD PUT CHECK ON THE     }
  1520.       {  GLOBALFREE() CALL TO VERIFY THAT IT EXECUTED    }
  1521.       {  PROPERLY.                                       }
  1522.       FOR i:=0 TO ((numreqs-1) DIV 2) DO
  1523.         BEGIN
  1524.           GlobalUnlock(memhandles[i+i]);
  1525.           globsize:=globsize+reqsizes[i+i];
  1526.           memhandles[i+i]:=GlobalFree(memhandles[i+i]);
  1527.       IF memhandles[i+i]<>0 THEN MessageBeep(0);
  1528.       END;
  1529.  
  1530.       { Go through the array of remaining blocks, issuing }
  1531.       {  a GlobalReAlloc on those blocks, expanding each  }
  1532.       {  so that it consumes remaining memory.  Then free }
  1533.       {  that block and go on to the next.                }
  1534.       FOR i:=0 TO ((numreqs-2) DIV 2) DO
  1535.       BEGIN
  1536.           temphand:=
  1537.           GlobalRealloc(memhandles[i+i+1],reqsizes[i+i+1]+globsize,memflags2);
  1538.       IF temphand<>0 THEN memhandles[i+i+1]:=temphand;
  1539.           memhandles[i+i+1]:=GlobalFree(memhandles[i+i+1]);
  1540.       IF memhandles[i+i+1]<>0 THEN MessageBeep(0);
  1541.           globsize:=globsize+reqsizes[i+i+1];
  1542.       END;
  1543.  
  1544.       { Stop timing and record results }
  1545.       StopStopWatch;
  1546.  
  1547.       { Increment iterations and accumulate seconds }
  1548.         Inc(iterarray[gmem_test_id]); 
  1549.          AccumTiming(gmem_test_id);
  1550.  
  1551.      END;  { While }
  1552.  
  1553. END;  { GMemTest }
  1554.  
  1555. { *************************** }
  1556. { GRAPHICS BENCHMARK ROUTINES }
  1557. { *************************** }
  1558.  
  1559. { **************** }
  1560. { Pixels benchmark }
  1561. PROCEDURE PixelTest;
  1562. VAR
  1563.     xmin, xmax: Integer;              { X clipping bounds }
  1564.     ymin, ymax: Integer;              { Y clipping bounds }
  1565.     xloc: ARRAY [0..pixels_per_iter] OF Integer;   { X coordinates array }
  1566.     yloc: ARRAY [0..pixels_per_iter] OF Integer;   { Y coordinates array }
  1567.     colors: ARRAY [0..pixels_per_iter] OF LongInt;    { Colors array }
  1568.     i: Word;                          { Loop index }
  1569.     tlongint: LongInt;                { Temp long integer }
  1570.     redval: Byte;                     { Holds RED value }
  1571.     greenval: Byte;                   { Holds GREEN value }
  1572.     blueval: Byte;                    { Holds BLUE value }
  1573.     HDevCont: HDC;                    { Device context }
  1574.   HisRect: TRect;                                        { Client rectangle }
  1575.   menuhand: HMenu;                                    { Handle for menu }
  1576.   omenuhand: HMenu;                                    { Old menu handle }
  1577. BEGIN
  1578.  
  1579.     { Set up the proper menu }
  1580.     menuhand:=LoadMenu(HInstance,'PIXMENU');
  1581.   omenuhand:=GetMenu(HByteWin);
  1582.   SetMenu(HByteWin,menuhand);
  1583.  
  1584.     { Determine the clipping bounds for this test.  }
  1585.   GetClientRect(HByteWin,HisRect);
  1586.     xmin:=HisRect.left;
  1587.     ymin:=HisRect.top;
  1588.     xmax:=HisRect.right;
  1589.     ymax:=HisRect.bottom;
  1590.  
  1591.     { Clear the timing arrays }
  1592.     elapsedtsecarray[pixel_test_id]:=0;
  1593.   iterarray[pixel_test_id]:=0;
  1594.  
  1595.     { Build an array of color references }
  1596.     FOR i:=0 TO pixels_per_iter DO
  1597.     BEGIN
  1598.       tlongint:=Randnum(0);
  1599.       redval:=ByteRec(WordRec(tlongint).lo).lo;
  1600.     tlongint:=Randnum(0);
  1601.     greenval:=ByteRec(WordRec(tlongint).lo).lo;
  1602.     tlongint:=Randnum(0);
  1603.     blueval:=ByteRec(WordRec(tlongint).lo).lo;
  1604.         colors[i]:=PaletteRGB(redval,greenval,blueval);
  1605.     END;
  1606.  
  1607.     { Get a device context }
  1608.     HDevCont:=GetDC(HByteWin);
  1609.  
  1610.     { ** SetPixel ** }
  1611.  
  1612.     { Enter timing loop }
  1613.     WHILE (elapsedtsecarray[pixel_test_id] DIV 1000)<pixel_secs  DO 
  1614.     BEGIN
  1615.              
  1616.         { Clear client window }
  1617.         EraseClient;
  1618.  
  1619.     { Build a random array of x and y locations }
  1620.     FOR i:=0 TO pixels_per_iter DO
  1621.     BEGIN
  1622.         tlongint:=xmax-xmin;
  1623.         tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
  1624.         xloc[i]:=WordRec(tlongint).lo;
  1625.         tlongint:=ymax-ymin;
  1626.         tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
  1627.         yloc[i]:=WordRec(tlongint).lo;
  1628.     END;
  1629.  
  1630.  
  1631.         { Start timing }
  1632.         StartStopWatch;
  1633.  
  1634.         { Step through array, writing pixels to screen }
  1635.     
  1636.         FOR i:=0 TO pixels_per_iter DO
  1637.             SetPixel(HDevCont,xloc[i],yloc[i],colors[i]);
  1638.  
  1639.         { Stop timing }
  1640.         StopStopWatch;
  1641.  
  1642.         { Increment iterations and accumulate seconds }
  1643.         Inc(iterarray[pixel_test_id]); 
  1644.          AccumTiming(pixel_test_id);
  1645.  
  1646.     END;  { While }
  1647.  
  1648. (*
  1649.  ** NOTE: The GetPixel test has been eliminated in this
  1650.  ** version of the benchmarks.  It seems to be a pointless
  1651.  ** test, since few applications use this feature.
  1652.  ** We may resurrect it in later versions. --RG
  1653.  **
  1654.  
  1655.     { ** GetPixel ** }
  1656.  
  1657.     { Enter timing loop }
  1658.     WHILE elapsedminarray[1]*60+elapsedtsecarray[1]<pixel_secs DO
  1659.     BEGIN
  1660.  
  1661.         { Start timing }
  1662.         StartStopWatch;
  1663.  
  1664.         { Step through the array, reading pixels }
  1665.  
  1666.         FOR i:=0 TO pixels_per_iter DO
  1667.             tlongint:=GetPixel(HDevCont,xloc[i],yloc[i]);
  1668.  
  1669.         { Stop timing }
  1670.         StopStopWatch;
  1671.  
  1672.         { Increment iterations and accumulate seconds }
  1673.         Inc(iterarray[1]);
  1674.         AccumTiming(1);
  1675.  
  1676.     END;  { While }
  1677.  *)
  1678.     { Show that we're done painting }
  1679.     ReleaseDC(HByteWin,HDevCont);
  1680.  
  1681.   { Put menu back the way it was }
  1682.   SetMenu(HByteWin,omenuhand);
  1683.   DestroyMenu(menuhand);
  1684.  
  1685. END;  { PixelTest }
  1686.  
  1687. { **************** }
  1688. { Make some pens   }
  1689. { This procedure is called prior to doing the graphics }
  1690. {  tests.  It creates a set of 8 pens and loads them  }
  1691. {  into the global array pens[].  The graphics tests   }
  1692. {  that use pens use the array pens[].                 }
  1693. PROCEDURE MakePens;
  1694. VAR  
  1695.     redval: Integer;          { Red value }
  1696.     greenval: Integer;        { Green value }
  1697.     blueval: Integer;         { Blue value }
  1698.     i: Integer;               { Index }
  1699.   j: Integer;                                { Another index }
  1700.     
  1701. BEGIN
  1702.  
  1703.     { Create a collection of pens...8 in all }
  1704.     redval:=0;
  1705.     greenval:=0;
  1706.     blueval:=0;
  1707.     FOR i:=0 TO 7 DO
  1708.     BEGIN
  1709.         IF (i AND 1)=1 THEN redval:=255 ELSE redval:=0;
  1710.         IF (i AND 2 )=2 THEN greenval:=255 ELSE greenval:=0;
  1711.         IF (i AND 4 )=4 THEN blueval:=255 ELSE blueval:=0;
  1712.         pens[i]:=CreatePen(ps_Solid,1,
  1713.             RGB(redval,greenval,blueval));
  1714.     END;  { FOR }
  1715.  
  1716. END;  { MakePens }
  1717.  
  1718. { ***************** }
  1719. { Delete those pens }
  1720. { Delete the pens make by MakePens () }
  1721. PROCEDURE DeletePens;
  1722. VAR
  1723.     i: Integer;             { Index }
  1724.  
  1725. BEGIN
  1726.  
  1727.     FOR i:=0 TO 7 DO
  1728.         DeleteObject(pens[i]);
  1729.  
  1730. END;  { DeletePens }
  1731.  
  1732. { *************** }
  1733. { Lines Benchmark }
  1734. PROCEDURE LineTest;
  1735.  
  1736. VAR
  1737.     xyloc: ARRAY [0..3,0..lines_per_iter] OF Integer; { Coordinates array }
  1738.     i: Word;                        { Index variable }
  1739.     j: Word;                        { Another index variable }
  1740.     tlongint: LongInt;              { Temporary long integer }
  1741.     HDevCont: HDC;                  { Device context }
  1742.   mypen: HPen;                                        { Current pen }
  1743.     xmin, xmax: Integer;              { X clipping bounds }
  1744.     ymin, ymax: Integer;              { Y clipping bounds }
  1745.   HisRect: TRect;                                        { Client rectangle }
  1746.   menuhand: HMenu;                                    { Handle for menu }
  1747.   omenuhand: HMenu;                                    { Old menu handle }
  1748.  
  1749. BEGIN
  1750.  
  1751.     { Set up the proper menu }
  1752.     menuhand:=LoadMenu(HInstance,'LINEMENU');
  1753.   omenuhand:=GetMenu(HByteWin);
  1754.   SetMenu(HByteWin,menuhand);
  1755.  
  1756.     { Make some pens }
  1757.   MakePens;
  1758.  
  1759.     { Clear the timing arrays }
  1760.     elapsedtsecarray[line_test_id]:=0;
  1761.   iterarray[line_test_id]:=0;
  1762.  
  1763.   { For now...no clipping }
  1764.   pref_settings[pref_clipamt_id]:=0;
  1765.  
  1766.     { Determine the clipping bounds for this test.  }
  1767.   GetClientRect(HByteWin,HisRect);
  1768.     xmin:=HisRect.left;
  1769.     ymin:=HisRect.top;
  1770.     xmax:=HisRect.right;
  1771.     ymax:=HisRect.bottom;
  1772.  
  1773.  
  1774.     { Begin the loop.  Execute inner loops until the outer-loop }
  1775.     {  number of seconds is satisfied.                          }
  1776.  
  1777.     WHILE (elapsedtsecarray[line_test_id] DIV 1000)<line_secs DO
  1778.     BEGIN
  1779.  
  1780.     { Build array of endpoints }
  1781.     FOR i:=0 TO lines_per_iter DO
  1782.         FOR j:=0 TO 1 DO
  1783.         BEGIN
  1784.         tlongint:=xmax-xmin+(2*pref_settings[pref_clipamt_id]);
  1785.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1786.       xyloc[j,i]:=WordRec(tlongint).lo+xmin-
  1787.                               pref_settings[pref_clipamt_id];
  1788.       tlongint:=ymax-ymin+(2*pref_settings[pref_clipamt_id]);
  1789.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1790.       xyloc[j+2,i]:=Wordrec(tlongint).lo+xmin-
  1791.                               pref_settings[pref_clipamt_id];
  1792.         END;
  1793.  
  1794.     { Clear the window }
  1795.     EraseClient;
  1796.  
  1797.         { Select a pen }
  1798.         tlongint:=ABS(GetRandWithCeiling(7));
  1799.         i:=WordRec(tlongint).lo;
  1800.  
  1801.         { Get a device context }
  1802.         HDevCont:=GetDC(HByteWin);
  1803.       SelectObject(HDevCont,pens[i]);
  1804.  
  1805.         { Start timing }
  1806.         StartStopWatch;
  1807.  
  1808.         { Draw lines }
  1809.         FOR j:=0 TO lines_per_iter DO
  1810.         BEGIN
  1811.             MoveTo(HDevCont,xyloc[0,j],xyloc[2,j]);
  1812.             LineTo(HDevCont,xyloc[1,j],xyloc[3,j]);
  1813.         END;
  1814.  
  1815.         { Stop timing and accumulate }
  1816.         StopStopWatch;
  1817.         Inc(iterarray[line_test_id]);
  1818.         AccumTiming(line_test_id);
  1819.  
  1820.         { Release the device context }
  1821.         ReleaseDC(HByteWin,HDevCont);
  1822.  
  1823.     END;  { WHILE }
  1824.  
  1825.   { Delete the pens }
  1826.   DeletePens;
  1827.  
  1828.   { Put menu back the way it was }
  1829.   SetMenu(HByteWin,omenuhand);
  1830.   DestroyMenu(menuhand);
  1831.  
  1832. END;  { LineTest }
  1833.  
  1834. { ******************* }
  1835. { PolyGons benchmark  }
  1836. PROCEDURE PolygonTest;
  1837. VAR
  1838.     ppoints: ARRAY[0..polys_per_iter*9] OF TPoint;
  1839.   npoints: ARRAY[0..polys_per_iter-1] OF Integer;
  1840.     HDevCont: HDC;                    { Device context }
  1841.   mypen: HPen;                                            { Current drawing pen }
  1842.   i: Integer;                                                { Index }
  1843.   tlongint: LongInt;                                { Temp long integer }
  1844.     xmin, xmax: Integer;              { X clipping bounds }
  1845.     ymin, ymax: Integer;              { Y clipping bounds }
  1846.   HisRect: TRect;                                        { Client rectangle }
  1847.   xloc, yloc: Word;                                    { Center points of polygon }
  1848.   menuhand: HMenu;                                    { Handle for menu }
  1849.   omenuhand: HMenu;                                    { Old menu handle }
  1850.  
  1851. BEGIN
  1852.  
  1853.     { Set up the proper menu }
  1854.     menuhand:=LoadMenu(HInstance,'POLYMENU');
  1855.   omenuhand:=GetMenu(HByteWin);
  1856.   SetMenu(HByteWin,menuhand);
  1857.  
  1858.     { Make some pens }
  1859.   MakePens;
  1860.  
  1861.     { Clear the timing arrays }
  1862.   elapsedtsecarray[poly_test_id]:=0;
  1863.   iterarray[poly_test_id]:=0;
  1864.  
  1865.   GetClientRect(HByteWin,HisRect);
  1866.     xmin:=HisRect.left-pref_settings[pref_clipamt_id];
  1867.     ymin:=HisRect.top-pref_settings[pref_clipamt_id];
  1868.     xmax:=HisRect.right+pref_settings[pref_clipamt_id];
  1869.     ymax:=HisRect.bottom+pref_settings[pref_clipamt_id];
  1870.  
  1871.     { Begin the loop.  Execute inner loops until the outer-loop }
  1872.     {  number of seconds is satisfied.                          }
  1873.     WHILE (elapsedtsecarray[poly_test_id] DIV 1000)<poly_secs DO
  1874.     BEGIN
  1875.  
  1876.         (**
  1877.      ** Build some polygons.
  1878.      ** This is an admittedly scary-looking algorithm that
  1879.      ** builds a guaranteed convex 8-sided [I think] polygon.
  1880.      **)
  1881.         FOR i:=0 TO polys_per_iter-1 DO
  1882.         BEGIN
  1883.       npoints[i]:=9;            { All polygons have 9 endpoints }
  1884.              tlongint:=xmax-xmin;
  1885.             tlongint:=ABS(GetRandWithCeiling(tlongint));
  1886.       xloc:=WordRec(tlongint).lo+xmin;
  1887.         tlongint:=ymax-ymin;
  1888.             tlongint:=ABS(GetRandWithCeiling(tlongint));
  1889.             yloc:=WordRec(tlongint).lo+ymin;
  1890.       ppoints[i*9].x:=xloc;
  1891.       tlongint:=yloc-ymin;
  1892.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1893.       ppoints[i*9].y:=yloc-WordRec(tlongint).lo;
  1894.       tlongint:=LMin(xmax-xloc,yloc-ymin);
  1895.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1896.       ppoints[i*9+1].x:=xloc+WordRec(tlongint).lo;
  1897.       ppoints[i*9+1].y:=yloc-WordRec(tlongint).lo;
  1898.       tlongint:=xmax-xloc;
  1899.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1900.       ppoints[i*9+2].x:=xloc+WordRec(tlongint).lo;
  1901.       ppoints[i*9+2].y:=yloc;
  1902.       tlongint:=LMin(ymax-yloc,xmax-xloc);
  1903.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1904.       ppoints[i*9+3].x:=xloc+WordRec(tlongint).lo;
  1905.       ppoints[i*9+3].y:=yloc+WordRec(tlongint).lo;
  1906.       tlongint:=ymax-yloc;
  1907.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1908.       ppoints[i*9+4].x:=xloc;
  1909.       ppoints[i*9+4].y:=yloc+WordRec(tlongint).lo;
  1910.       tlongint:=LMin(xloc-xmin,ymax-yloc);
  1911.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1912.       ppoints[i*9+5].x:=xloc-WordRec(tlongint).lo;
  1913.       ppoints[i*9+5].y:=yloc+WordRec(tlongint).lo;
  1914.       tlongint:=xloc-xmin;
  1915.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1916.       ppoints[i*9+6].x:=xloc-WordRec(tlongint).lo;
  1917.       ppoints[i*9+6].y:=yloc;
  1918.       tlongint:=Lmin(yloc-ymin,xloc-xmin);
  1919.       tlongint:=ABS(GetRandWithCeiling(tlongint));
  1920.       ppoints[i*9+7].x:=xloc-WordRec(tlongint).lo;
  1921.       ppoints[i*9+7].y:=yloc-WordRec(tlongint).lo;
  1922.       ppoints[i*9+8].x:=ppoints[i*9].x;
  1923.       ppoints[i*9+8].y:=ppoints[i*9].y;
  1924.  
  1925.         END;
  1926.  
  1927.       { Erase the window }
  1928.     EraseClient;
  1929.  
  1930.         { Get a device context }
  1931.         HDevCont:=GetDC(HByteWin);
  1932.     SetPolyFillMode(HdevCont,Winding);
  1933.  
  1934.         { Select a pen }
  1935.         tlongint:=ABS(GetRandWithCeiling(7));
  1936.         i:=WordRec(tlongint).lo;
  1937.         mypen:=SelectObject(HDevCont,pens[i]);
  1938.  
  1939.     { Select a brush }
  1940.     tlongint:=ABS(GetRandWithCeiling(10));
  1941.     SelectObject(HdevCont,GetStockObject(brush_style[tlongint]));
  1942.  
  1943.         { Start timing }
  1944.          StartStopWatch; 
  1945.  
  1946.         { Draw polygons }
  1947.          PolyPolygon(HDevCont,ppoints,npoints,polys_per_iter-1); 
  1948.  
  1949.          { Stop timing }
  1950.         StopStopWatch;
  1951.  
  1952.         { Release the device context }
  1953.         ReleaseDC(HByteWin,HDevCont);
  1954.  
  1955.         { Accumulate results }
  1956.         Inc(iterarray[poly_test_id]);
  1957.         AccumTiming(poly_test_id);
  1958.  
  1959.     END;  { WHILE }
  1960.  
  1961.   { Delete the pens }
  1962.   DeletePens;
  1963.  
  1964.   { Put menu back the way it was }
  1965.   SetMenu(HByteWin,omenuhand);
  1966.   DestroyMenu(menuhand);
  1967.  
  1968. END;  { PolygonTest }
  1969.  
  1970. { ******************** }
  1971. { Rectangles Benchmark }
  1972. PROCEDURE RectTest;
  1973. VAR
  1974.     rpoints: ARRAY [0..3,0..rects_per_iter] OF Integer; { Rect. points }
  1975.   mypen: HPen;                                                        { Current pen }
  1976.     i: Integer;                             { Index }
  1977.     tlongint: LongInt;                      { Temp. for long int. }
  1978.   halfx: LongInt;                                                    { Half the allowed x range }
  1979.   halfy: LongInt;                                                    { Half the allowed y range }
  1980.     HDevCont: HDC;                          { Device context }
  1981.     xmin, xmax: Integer;              { X clipping bounds }
  1982.     ymin, ymax: Integer;              { Y clipping bounds }
  1983.   HisRect: TRect;                                        { Client rectangle }
  1984.   menuhand: HMenu;                                    { Handle for menu }
  1985.   omenuhand: HMenu;                                    { Old menu handle }
  1986.  
  1987. BEGIN
  1988.  
  1989.     { Set up the proper menu }
  1990.     menuhand:=LoadMenu(HInstance,'RECTMENU');
  1991.   omenuhand:=GetMenu(HByteWin);
  1992.   SetMenu(HByteWin,menuhand);
  1993.  
  1994.     { Make some pens }
  1995.   MakePens;
  1996.  
  1997.     { Clear the timing arrays }
  1998.   elapsedtsecarray[rect_test_id]:=0;
  1999.   iterarray[rect_test_id]:=0;
  2000.  
  2001.     { Determine the clipping bounds for this test.  }
  2002.   GetClientRect(HByteWin,HisRect);
  2003.     xmin:=HisRect.left;
  2004.     ymin:=HisRect.top;
  2005.     xmax:=HisRect.right;
  2006.     ymax:=HisRect.bottom;
  2007.   halfx:=(xmax-xmin+(2*pref_settings[pref_clipamt_id]))
  2008.               DIV 2;
  2009.   halfy:=(ymax-ymin+(2*pref_settings[pref_clipamt_id]))
  2010.                   DIV 2;
  2011.  
  2012.  
  2013.     { Begin the loop.  Execute inner loops until the outer-loop }
  2014.     {  number of seconds is satisfied.                          }
  2015.     WHILE (elapsedtsecarray[rect_test_id])/1000<rect_secs DO
  2016.     BEGIN
  2017.  
  2018.      { Fill the array of rectangle points.        }
  2019.     {  rpoints[0,i],rpoints[1,i] = x,y of ULHC   }
  2020.     {  rpoints[2,i],rpoints[3,i] = x,y or LRHC   }
  2021.     FOR i:=0 TO rects_per_iter DO
  2022.         BEGIN
  2023.       tlongint:=ABS(GetRandWithCeiling(halfx));
  2024.       rpoints[0,i]:=WordRec(tlongint).lo+xmin-
  2025.                   pref_settings[pref_clipamt_id];
  2026.       tlongint:=ABS(GetRandWithCeiling(halfy));
  2027.       rpoints[1,i]:=WordRec(tlongint).lo+ymin-
  2028.                   pref_settings[pref_clipamt_id];
  2029.       tlongint:=ABS(GetRandWithCeiling(halfx));
  2030.       rpoints[2,i]:=WordRec(tlongint).lo+((xmax-xmin) DIV 2);
  2031.       tlongint:=ABS(GetRandWithCeiling(halfy));
  2032.       rpoints[3,i]:=WordRec(tlongint).lo+((ymax-ymin) DIV 2);
  2033.         END;  { FOR }
  2034.  
  2035.     { Clear drawing area }
  2036.     EraseClient;
  2037.  
  2038.         { Get a device context }
  2039.         HDevCont:=GetDC(HByteWin);
  2040.  
  2041.       { Set the current brush to hollow }
  2042.       SelectObject(HDevCont,GetStockObject(Hollow_Brush));
  2043.  
  2044.         { Select a pen }
  2045.         tlongint:=ABS(GetRandWithCeiling(7));
  2046.         i:=WordRec(tlongint).lo;
  2047.         mypen:=SelectObject(HDevCont,pens[i]);
  2048.  
  2049.         { Start timing }
  2050.         StartStopWatch;
  2051.  
  2052.         { Draw rectangles }
  2053.         FOR i:=0 TO rects_per_iter DO
  2054.             Rectangle(HDevCont,rpoints[0,i],rpoints[1,i],
  2055.                         rpoints[2,i],rpoints[3,i]);
  2056.  
  2057.         { Stop timing }
  2058.         StopStopWatch;
  2059.  
  2060.     { Release DC }
  2061.     ReleaseDC(HByteWin,HDevCont);
  2062.  
  2063.         { Accumulate results }
  2064.         Inc(iterarray[rect_test_id]);
  2065.         AccumTiming(rect_test_id);
  2066.  
  2067.     END;  { WHILE }
  2068.  
  2069.   { Delete the pens }
  2070.   DeletePens;
  2071.  
  2072.   { Put menu back the way it was }
  2073.   SetMenu(HByteWin,omenuhand);
  2074.   DestroyMenu(menuhand);
  2075.  
  2076. END;  { RectTest }
  2077.  
  2078. { ******************** }
  2079. {   Ellipses Benchmark }
  2080. PROCEDURE EllipseTest;
  2081. VAR
  2082.     rpoints: ARRAY [0..3,0..ellps_per_iter] OF Integer; { Rect. points }
  2083.   mypen: HPen;                                                        { Current pen }
  2084.     i: Integer;                             { Index }
  2085.     tlongint: LongInt;                      { Temp. for long int. }
  2086.   halfx: LongInt;                                                    { Half the allowed x range }
  2087.   halfy: LongInt;                                                    { Half the allowed y range }
  2088.     HDevCont: HDC;                          { Device context }
  2089.     xmin, xmax: Integer;              { X clipping bounds }
  2090.     ymin, ymax: Integer;              { Y clipping bounds }
  2091.   HisRect: TRect;                                        { Client rectangle }
  2092.   menuhand: HMenu;                                    { Handle for menu }
  2093.   omenuhand: HMenu;                                    { Old menu handle }
  2094.  
  2095. BEGIN
  2096.  
  2097.     { Set up the proper menu }
  2098.     menuhand:=LoadMenu(HInstance,'ELLMENU');
  2099.   omenuhand:=GetMenu(HByteWin);
  2100.   SetMenu(HByteWin,menuhand);
  2101.  
  2102.     { Make some pens }
  2103.   MakePens;
  2104.  
  2105.     { Clear the timing arrays }
  2106.   elapsedtsecarray[arce_test_id]:=0;
  2107.   iterarray[arce_test_id]:=0;
  2108.  
  2109.     { Determine the clipping bounds for this test.  }
  2110.   GetClientRect(HByteWin,HisRect);
  2111.     xmin:=HisRect.left;
  2112.     ymin:=HisRect.top;
  2113.     xmax:=HisRect.right;
  2114.     ymax:=HisRect.bottom;
  2115.   halfx:=(xmax-xmin+(2*pref_settings[pref_clipamt_id]))
  2116.               DIV 2;
  2117.   halfy:=(ymax-ymin+(2*pref_settings[pref_clipamt_id]))
  2118.                   DIV 2;
  2119.  
  2120.  
  2121.     { Begin the loop.  Execute inner loops until the outer-loop }
  2122.     {  number of seconds is satisfied.                          }
  2123.     WHILE (elapsedtsecarray[arce_test_id] DIV 1000)<arce_secs DO
  2124.     BEGIN
  2125.  
  2126.      { Fill the array of rectangle points.        }
  2127.     {  rpoints[0,i],rpoints[1,i] = x,y of ULHC   }
  2128.     {  rpoints[2,i],rpoints[3,i] = x,y or LRHC   }
  2129.     FOR i:=0 TO ellps_per_iter DO
  2130.         BEGIN
  2131.       tlongint:=ABS(GetRandWithCeiling(halfx));
  2132.       rpoints[0,i]:=WordRec(tlongint).lo+xmin-
  2133.                   pref_settings[pref_clipamt_id];
  2134.       tlongint:=ABS(GetRandWithCeiling(halfy));
  2135.       rpoints[1,i]:=WordRec(tlongint).lo+ymin-
  2136.                   pref_settings[pref_clipamt_id];
  2137.       tlongint:=ABS(GetRandWithCeiling(halfx));
  2138.       rpoints[2,i]:=WordRec(tlongint).lo+((xmax-xmin) DIV 2);
  2139.       tlongint:=ABS(GetRandWithCeiling(halfy));
  2140.       rpoints[3,i]:=WordRec(tlongint).lo+((ymax-ymin) DIV 2);
  2141.         END;  { FOR }
  2142.  
  2143.     { Clear drawing area }
  2144.     EraseClient;
  2145.  
  2146.         { Get a device context }
  2147.         HDevCont:=GetDC(HByteWin);
  2148.  
  2149.       { Set the current brush to hollow }
  2150.       SelectObject(HDevCont,GetStockObject(Hollow_Brush));
  2151.  
  2152.         { Select a pen }
  2153.         tlongint:=ABS(GetRandWithCeiling(7));
  2154.         i:=WordRec(tlongint).lo;
  2155.         mypen:=SelectObject(HDevCont,pens[i]);
  2156.  
  2157.         { Start timing }
  2158.         StartStopWatch;
  2159.  
  2160.         { Draw ellipses }
  2161.         FOR i:=0 TO ellps_per_iter DO
  2162.             Ellipse(HDevCont,rpoints[0,i],rpoints[1,i],
  2163.                         rpoints[2,i],rpoints[3,i]);
  2164.  
  2165.         { Stop timing }
  2166.         StopStopWatch;
  2167.  
  2168.     { Release DC }
  2169.     ReleaseDC(HByteWin,HDevCont);
  2170.  
  2171.         { Accumulate results }
  2172.         Inc(iterarray[arce_test_id]);
  2173.         AccumTiming(arce_test_id);
  2174.  
  2175.     END;  { WHILE }
  2176.  
  2177.   { Delete the pens }
  2178.   DeletePens;
  2179.  
  2180.   { Put menu back the way it was }
  2181.   SetMenu(HByteWin,omenuhand);
  2182.   DestroyMenu(menuhand);
  2183.  
  2184. END;  { RectTest }
  2185.  
  2186. (*****************
  2187.  ** BITMAP Test **
  2188.  *)
  2189. PROCEDURE BitbltTest;
  2190. VAR
  2191.     xdest: ARRAY [0..bmap_points] OF Integer;    { Dest x coordinates }
  2192.   ydest: ARRAY [0..bmap_points] OF Integer;    { Dest y coordinates }
  2193.   HDevCont: HDC;                                        { Device context }
  2194.   HMDevCont: HDC;                                        { Memory device context }
  2195.   bithand: HBitmap;                                    { Bitmap handle }
  2196.   i: Word;                                                    { Index }
  2197.   tlongint: Longint;                                { Temporary long }
  2198.   HisRect: TRect;                                        { Client rectangle }
  2199.     xmin, xmax: Integer;              { X clipping bounds }
  2200.     ymin, ymax: Integer;              { Y clipping bounds }
  2201.   menuhand: HMenu;                                    { Handle for menu }
  2202.   omenuhand: HMenu;                                    { Old menu handle }
  2203.  
  2204. BEGIN
  2205.  
  2206.     { Set up the proper menu }
  2207.     menuhand:=LoadMenu(HInstance,'BITMENU');
  2208.   omenuhand:=GetMenu(HByteWin);
  2209.   SetMenu(HByteWin,menuhand);
  2210.  
  2211.     { Clear the timing arrays }
  2212.     elapsedtsecarray[bitblt_test_id]:=0;
  2213.   iterarray[bitblt_test_id]:=0;
  2214.  
  2215.   { Determine clipping bounds for this test }
  2216.   GetClientRect(HByteWin,HisRect);
  2217.     xmin:=HisRect.left;
  2218.     ymin:=HisRect.top;
  2219.     xmax:=HisRect.right-bmap_size;
  2220.     ymax:=HisRect.bottom-bmap_size;
  2221.  
  2222.   { Load the bitmap }
  2223.   bithand:=LoadBitMap(HInstance,'BERM');
  2224.  
  2225.   { Begin the loop...execute inner loop until time expires }
  2226.     WHILE (elapsedtsecarray[bitblt_test_id] DIV 1000)<bitblt_secs DO
  2227.     BEGIN
  2228.       { Generate a random collection of destination points }
  2229.     FOR i:=0 TO bmap_points DO
  2230.     BEGIN
  2231.         tlongint:=xmax-xmin;
  2232.       tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
  2233.       xdest[i]:=WordRec(tlongint).lo;
  2234.       tlongint:=ymax-ymin;
  2235.       tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
  2236.       ydest[i]:=WordRec(tlongint).lo;
  2237.     END;
  2238.  
  2239.       { Get a context }
  2240.         HDevCont:=GetDC(HByteWin);
  2241.  
  2242.       { Clear the client rectangle }
  2243.     EraseClient;
  2244.  
  2245.       { Get a memory context }
  2246.     HMDevCont:=CreateCompatibleDC(HDevCont);
  2247.  
  2248.       { Put our bitmap in the memory context }
  2249.     SelectObject(HMDevCont,bithand);
  2250.  
  2251.       { Start timing }
  2252.     StartStopWatch;
  2253.  
  2254.       { Copy bitmap into first screen slot }
  2255.     BitBlt(HDevCont,xdest[0],ydest[0],bmap_size,bmap_size,
  2256.         HMDevCont,0,0,SrcCopy);
  2257.  
  2258.       { Loop...copying bitmap from source to destination }
  2259.     FOR i:=1 TO bmap_points DO
  2260.         BitBlt(HDevCont,xdest[i],ydest[i],bmap_size,bmap_size,
  2261.           HDevCont,xdest[i-1],ydest[i-1],SrcCopy);
  2262.  
  2263.       { Stop timing}
  2264.     StopStopWatch;
  2265.  
  2266.       { Release context }
  2267.     ReleaseDC(HByteWin,HDevCont);
  2268.     DeleteDC(HMDevCont);
  2269.  
  2270.       { Accumulate results }
  2271.       Inc(iterarray[bitblt_test_id]);
  2272.         AccumTiming(bitblt_test_id);
  2273.   END;
  2274.  
  2275.   { Dump the bitmap }
  2276.   DeleteObject(bithand);
  2277.  
  2278.   { Put menu back the way it was }
  2279.   SetMenu(HByteWin,omenuhand);
  2280.   DestroyMenu(menuhand);
  2281.  
  2282. END;    { BitmapTest }
  2283.  
  2284. (********************
  2285.  ** Text benchmark **
  2286.  *)
  2287. PROCEDURE TextTest;
  2288. VAR
  2289.   locs: ARRAY[1..text_per_iter] of TRect;    { Coords for text }
  2290.   HisRect: TRect;                                        { Client rectangle }
  2291.     xmin, xmax: Integer;              { X clipping bounds }
  2292.     ymin, ymax: Integer;              { Y clipping bounds }
  2293.     myfont: ARRAY[0..2] of HFont;            { Logical font record }
  2294.   mytext: ARRAY[0..80] of Char;            { Local sentence }
  2295.   mytextlen: Integer;                                { Length of string }
  2296.   mytexthi: Integer;                                { Height of string }
  2297.   mytextwide: Integer;                            { Width of string }
  2298.   textxmax: Integer;                                { Max text start x }
  2299.   textymax: Integer;                                { Max text start y }
  2300.   rectxmin: Integer;                                { Min rectangle x }
  2301.   rectymin: Integer;                                { Min rectangly y }
  2302.   i: Integer;                                                { Index and stuff }
  2303.   tlongint: Longint;                                { Temp long integer }
  2304.   HDevCont: HDC;                                        { Device context }
  2305.   redval, greenval, blueval: Byte;    { Colors }
  2306.   myformat: Word;                                        { Format }
  2307.   menuhand: HMenu;                                    { Handle for menu }
  2308.   omenuhand: HMenu;                                    { Old menu handle }
  2309.  
  2310. BEGIN
  2311.  
  2312.     { Set up the proper menu }
  2313.     menuhand:=LoadMenu(HInstance,'TEXTMENU');
  2314.   omenuhand:=GetMenu(HByteWin);
  2315.   SetMenu(HByteWin,menuhand);
  2316.  
  2317.     { Clear the timing arrays }
  2318.     elapsedtsecarray[texto_test_id]:=0;
  2319.   iterarray[texto_test_id]:=0;
  2320.   elapsedtsecarray[dtext_test_id]:=0;
  2321.   iterarray[dtext_test_id]:=0;
  2322.  
  2323.   { Determine the rectangle bounds }
  2324.   GetClientRect(HByteWin,HisRect);
  2325.     xmin:=HisRect.left;
  2326.     ymin:=HisRect.top;
  2327.     xmax:=HisRect.right;
  2328.     ymax:=HisRect.bottom;
  2329.  
  2330.   { Create some logical fonts }
  2331.  
  2332.   { Height=10, Width=8, Normal, Not Italic, Not Underlined,
  2333.     No Strikeout, ANSI characterset, Default Precision,
  2334.     default Clip Precision, Default Quality,Default Pitch,
  2335.     System Typeface }
  2336.   myfont[0]:=CreateFont(10,8,0,0,400,0,0,0,ANSI_CHARSET,
  2337.                           OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2338.               DEFAULT_QUALITY, DEFAULT_PITCH, 'System');
  2339.  
  2340.   { Height=20, Width=16, Bold, Not Italic, Not Underlined,
  2341.     No Strikeout, ANSI characterset, default precision,
  2342.     default clip precision, default quality,Default Pitch,
  2343.     Helvetica typeface }
  2344.   myfont[1]:=CreateFont(20,16,0,0,700,0,0,0,ANSI_CHARSET,
  2345.                           OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2346.               DEFAULT_QUALITY, DEFAULT_PITCH,'Helv');
  2347.  
  2348.   { Height=16, width=10, Normal, Italic, Not Underlined,
  2349.       No strikeout, ANSI characterset, default precision,
  2350.     default clip precision, default quality, default pitch,
  2351.     Courier typeface }
  2352.   myfont[2]:=CreateFont(16,10,0,0,400,1,0,0,ANSI_CHARSET,
  2353.                           OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  2354.               DEFAULT_QUALITY, DEFAULT_PITCH,'Script');
  2355.  
  2356.   { Begin the loop...execute inner loop until time expires }
  2357.     WHILE (elapsedtsecarray[texto_test_id] DIV 1000)<text_secs DO
  2358.     BEGIN
  2359.  
  2360.       { Select a sentence into the local variable }
  2361.     tlongint:=5;
  2362.     tlongint:=ABS(GetRandWithCeiling(tlongint));
  2363.     StrPCopy(mytext,bench_strs[tlongint]);
  2364.     mytextlen:=StrLen(mytext);
  2365.  
  2366.       { Get a context }
  2367.         HDevCont:=GetDC(HByteWin);
  2368.  
  2369.     { Set the text color }
  2370.     tlongint:=RandNum(0);
  2371.     i:=WordRec(tlongint).lo;
  2372.     redval:=ByteRec(i).lo;
  2373.     tlongint:=RandNum(0);
  2374.     i:=WordRec(tlongint).lo;
  2375.     greenval:=ByteRec(i).lo;
  2376.     tlongint:=RandNum(0);
  2377.     i:=WordRec(tlongint).lo;
  2378.     blueval:=ByteRec(i).lo;
  2379.     SetTextColor(HDevCont,RGB(redval,greenval,blueval));
  2380.  
  2381.     { Set the background }
  2382.     SetBkColor(HDevCont,RGB(0,0,0));
  2383.  
  2384.     IF ((RandNum(0) AND 1) = 1) THEN
  2385.         SetBkMode(HDevCont,Opaque)
  2386.     ELSE
  2387.         SetBkMode(HDevCont,Transparent);
  2388.  
  2389.     { Randomly pick a logical font }
  2390.     tlongint:=ABS(GetRandWithCeiling(2));
  2391.         SelectObject(HDevCont,myfont[tlongint]);
  2392.  
  2393.     { Determine the range of allowed origin coordinates }
  2394.     tlongint:=GetTextExtent(HDevCont,mytext,mytextlen);
  2395.         mytexthi:=WordRec(tlongint).hi;
  2396.     mytextwide:=WordRec(tlongint).lo;
  2397.         textxmax:=xmax-mytextwide-1;
  2398.     IF textxmax<0 THEN
  2399.         textxmax:=xmin+10;
  2400.     textymax:=ymax-mytexthi-1;
  2401.     IF textymax<0 THEN
  2402.         textymax:=ymin+10;
  2403.  
  2404.     { Randomly select an array of starting coordinates }
  2405.     FOR i:=1 TO text_per_iter DO
  2406.     BEGIN
  2407.       tlongint:=textxmax-xmin;
  2408.         tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
  2409.       locs[i].left:=tlongint;
  2410.       tlongint:=textymax-ymin;
  2411.       tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
  2412.       locs[i].top:=tlongint;
  2413.     END;    { FOR }
  2414.  
  2415.       { Clear the client rectangle }
  2416.     EraseClient;
  2417.  
  2418.       { Start timing }
  2419.     StartStopWatch;
  2420.  
  2421.     { Step through the array of coordinates, display sentence }
  2422.         FOR i:=1 to text_per_iter DO
  2423.         TextOut(HDevCont,locs[i].left,locs[i].top,@mytext,mytextlen);
  2424.  
  2425.       { Stop timing}
  2426.     StopStopWatch;
  2427.  
  2428.       { Release context }
  2429.     ReleaseDC(HByteWin,HDevCont);
  2430.  
  2431.       { Accumulate results }
  2432.       Inc(iterarray[texto_test_id]);
  2433.         AccumTiming(texto_test_id);
  2434.  
  2435.   END;    { WHILE }
  2436.  
  2437.   { Begin the loop...execute inner loop until time expires }
  2438.     WHILE (elapsedtsecarray[dtext_test_id] DIV 1000)<text_secs DO
  2439.     BEGIN
  2440.  
  2441.       { Select a sentence into the local variable }
  2442.     tlongint:=5;
  2443.     tlongint:=ABS(GetRandWithCeiling(tlongint));
  2444.     StrPCopy(mytext,bench_strs[tlongint]);
  2445.     mytextlen:=StrLen(mytext);
  2446.  
  2447.       { Get a context }
  2448.         HDevCont:=GetDC(HByteWin);
  2449.  
  2450.     { Set the text color }
  2451.     tlongint:=RandNum(0);
  2452.     i:=WordRec(tlongint).lo;
  2453.     redval:=ByteRec(i).lo;
  2454.     tlongint:=RandNum(0);
  2455.     i:=WordRec(tlongint).lo;
  2456.     greenval:=ByteRec(i).lo;
  2457.     tlongint:=RandNum(0);
  2458.     i:=WordRec(tlongint).lo;
  2459.     blueval:=ByteRec(i).lo;
  2460.     SetTextColor(HDevCont,RGB(redval,greenval,blueval));
  2461.  
  2462.     { Set the background }
  2463.     SetBkColor(HDevCont,RGB(0,0,0));
  2464.  
  2465.     IF ((RandNum(0) AND 1) = 1) THEN
  2466.         SetBkMode(HDevCont,Opaque)
  2467.     ELSE
  2468.         SetBkMode(HDevCont,Transparent);
  2469.  
  2470.     { Randomly pick a logical font }
  2471.     tlongint:=ABS(GetRandWithCeiling(2));
  2472.         SelectObject(HDevCont,myfont[tlongint]);
  2473.  
  2474.     { Determine the range of allowed origin coordinates }
  2475.     tlongint:=GetTextExtent(HDevCont,mytext,mytextlen);
  2476.         mytexthi:=WordRec(tlongint).hi;
  2477.     mytextwide:=WordRec(tlongint).lo;
  2478.         textxmax:=xmax-mytextwide-1;
  2479.     IF textxmax<0 THEN
  2480.         textxmax:=xmin+10;
  2481.     textymax:=ymax-mytexthi-1;
  2482.     IF textymax<0 THEN
  2483.         textymax:=ymin+10;
  2484.  
  2485.     { Determine range of allowed rectangle extents }
  2486.     rectxmin:=mytextwide DIV 3;
  2487.     rectymin:=mytexthi DIV 3;
  2488.  
  2489.     { Create array of random rectangles }
  2490.     FOR i:=1 TO text_per_iter DO
  2491.     BEGIN
  2492.         tlongint:=textxmax-xmin;
  2493.         tlongint:=ABS(GetRandWithCeiling(tlongint))+xmin;
  2494.         locs[i].left:=WordRec(tlongint).lo;
  2495.       tlongint:=textymax-ymin;
  2496.       tlongint:=ABS(GetRandWithCeiling(tlongint))+ymin;
  2497.       locs[i].top:=WordRec(tlongint).lo;
  2498.       tlongint:=xmax-rectxmin;
  2499.       tlongint:=ABS(GetRandWithCeiling(tlongint))+rectxmin;
  2500.       locs[i].right:=WordRec(tlongint).lo;
  2501.       tlongint:=ymax-rectymin;
  2502.       tlongint:=ABS(GetRandWithCeiling(tlongint))+rectymin;
  2503.       locs[i].bottom:=WordRec(tlongint).lo;
  2504.     END;
  2505.  
  2506.     { Select a format }
  2507.     tlongint:=RandNum(0);
  2508.     IF ((tlongint AND 1)=1) THEN
  2509.         myformat:=DT_LEFT
  2510.     ELSE
  2511.         myformat:=DT_RIGHT;
  2512.  
  2513.     IF((tlongint AND 2)=2) THEN
  2514.         myformat:=myformat OR DT_TOP
  2515.     ELSE
  2516.         myformat:=myformat OR DT_CENTER;
  2517.  
  2518.     myformat:=myformat OR DT_WORDBREAK;
  2519.  
  2520.       { Clear the client rectangle }
  2521.     EraseClient;
  2522.  
  2523.       { Start timing }
  2524.     StartStopWatch;
  2525.  
  2526.     { Step through the array of coordinates, display sentence }
  2527.         FOR i:=1 to text_per_iter DO
  2528.         DrawText(HdevCont,@mytext,mytextlen,locs[i],myformat);
  2529.  
  2530.       { Stop timing}
  2531.     StopStopWatch;
  2532.  
  2533.       { Release context }
  2534.     ReleaseDC(HByteWin,HDevCont);
  2535.  
  2536.       { Accumulate results }
  2537.       Inc(iterarray[dtext_test_id]);
  2538.         AccumTiming(dtext_test_id);
  2539.  
  2540.   END;    { WHILE }
  2541.  
  2542.   { We don't need the logical fonts anymore }
  2543.   FOR i:=0 TO 2 DO
  2544.       DeleteObject(myfont[i]);
  2545.  
  2546.   { Put menu back the way it was }
  2547.   SetMenu(HByteWin,omenuhand);
  2548.   DestroyMenu(menuhand);
  2549.  
  2550. END;
  2551.  
  2552. (**********************
  2553. ** Sequential file I/O
  2554. *)
  2555. PROCEDURE SFile_IO;
  2556. VAR
  2557.     fhandle: Integer;                                { File handle }
  2558.     openbuf: TOFStruct;                            { Open file buffer }
  2559.   fbuff: ARRAY [0..8191] OF Char;    { I/O buffer }
  2560.   offset: LongInt;                                { File offset }
  2561.     i: LongInt;                                            { Index }
  2562.   j: Integer;                                            { Another index }
  2563.   outstr:  Array [0..80] of Char; { message to display }
  2564.   outstrlen: Integer;             { need to know how long it is }
  2565.  
  2566. BEGIN
  2567.  
  2568.   { erase the screen and let user know what we are doing }
  2569.     InitBenchDisplay;
  2570.  
  2571.   strPCopy( @outstr, 'Starting sequential file i/o test.');
  2572.   outstrlen := StrLen( @outstr );
  2573.   DisplayBenchLine( @outstr, outstrlen );
  2574.   
  2575.   StrPCopy( @outstr, 'Creating test file.');
  2576.   outstrlen := StrLen( @outstr );
  2577.   DisplayBenchLine( @outstr, outstrlen );
  2578.   
  2579.   { Try to create the workfile.  If we can do it, fine. }
  2580.   { Otherwise, tell the user we failed, delete the file, }
  2581.   { and bail out. }
  2582.   fhandle:=Openfile('BYTE.TMP',openbuf,of_Create);
  2583.   IF fhandle=-1 THEN
  2584.   BEGIN
  2585.       { Tell of failure }
  2586.  
  2587.     EXIT;
  2588.   END;
  2589.  
  2590.   { initialize the buffer with write values. }
  2591.   FOR i:=0 TO 8191 DO
  2592.       fbuff[i]:='B';
  2593.  
  2594.   { initialize the file for output }
  2595.   FOR i:=1 TO sfilesize DIV 1000 DO
  2596.   BEGIN
  2597.       j:=_lwrite(fhandle,@fbuff,1000);
  2598.     IF j=-1 THEN
  2599.     BEGIN
  2600.         { Failed to write the file...tell user }
  2601.  
  2602.       _lclose(fhandle);
  2603.       Openfile('BYTE.TMP',openbuf,of_Delete);
  2604.       EXIT;
  2605.     END;
  2606.   END;    { FOR }
  2607.  
  2608.  
  2609.   StrPCopy( @outstr, 'Starting sequential file read test.' );
  2610.   outstrlen := StrLen( @outstr );
  2611.   DisplayBenchLine( @outstr, outstrlen );
  2612.   
  2613.  
  2614.   { really start the test }
  2615.   elapsedtsecarray[sfio_test_id] := 0;
  2616.   iterarray[sfio_test_id] := 1;         { we're only doing this 1x}
  2617.   StartStopWatch;
  2618.  
  2619.   { READ loop.  Pass through the file 4 times, once for }
  2620.   {  each record length selected in configuration.      }
  2621.   FOR i:=0 TO 3 DO
  2622.   BEGIN
  2623.       _llseek(fhandle,0,0);                    { Rewind }
  2624.     offset:=0;
  2625.     WHILE offset+sfilereclen[i]<=sfilesize DO
  2626.     BEGIN
  2627.         _lread(fhandle,@fbuff,sfilereclen[i]);
  2628.       offset:=offset+sfilereclen[i];
  2629.     END;    { WHILE }
  2630.     END;    { FOR }
  2631.  
  2632.   { test half over. stop the clock. Tell people we're working. Restart clock }
  2633.   StopStopWatch;
  2634.   AccumTiming( sfio_test_id );
  2635.   
  2636.   StrPCopy( @outstr, 'Starting sequential file write test.' );
  2637.   outstrlen := StrLen( @outstr );
  2638.   DisplayBenchLine( @outstr, outstrlen );
  2639.   
  2640.   StartStopWatch;
  2641.  { WRITE loop. Pass through the file 4 times, writing  }
  2642.   {  records in chunks same as the READ loop.           }
  2643.   FOR i:=0 TO 3 DO
  2644.   BEGIN
  2645.       _llseek(fhandle,0,0);                    { Rewind }
  2646.     offset:=0;
  2647.     WHILE offset+sfilereclen[i]<=sfilesize DO
  2648.     BEGIN
  2649.         _lwrite(fhandle,@fbuff,sfilereclen[i]);
  2650.       offset:=offset+sfilereclen[i];
  2651.     END;  { WHILE }
  2652.   END;        { FOR }
  2653.  
  2654.  
  2655.   { test over -- pickup the timings.}
  2656.   StopStopWatch;
  2657.   AccumTiming( sfio_test_id );
  2658.  
  2659.   { All done.  Record results and delete the file. }
  2660.   _lclose(fhandle);
  2661.   Openfile('BYTE.TMP',openbuf,of_Delete);
  2662.   EraseClient;
  2663.  
  2664. END;
  2665.  
  2666.  
  2667. { given an offset, return a uniqe file name }
  2668. PROCEDURE gfName( offset : Integer; VAR retStr:FileName );
  2669. VAR
  2670.   s: FileName;
  2671.  
  2672. BEGIN
  2673.   StrPCopy( retStr, 'BYTEDAT.' );
  2674.   Str( offset, s );
  2675.   StrCat(retStr, s);
  2676. END;
  2677.  
  2678.  
  2679. {********************
  2680. ** Create files for random file i/o.
  2681. ** Accumulate the number of bytes written to the files.
  2682. *}
  2683. PROCEDURE createFiles( fnum:integer; VAR myMax: LongInt );
  2684. CONST
  2685.    wvector: ARRAY[0..19] of LongInt = ( 4000, 1000,  500,  2800,  2500,
  2686.                                         1400, 8000, 8800,   300, 21111,
  2687.                                         2000, 6000,  200, 48800,  1300,
  2688.                                         9870, 3000, 2816,  8660,   127 );
  2689. VAR
  2690.   i: INTEGER;
  2691.   s: FileName;
  2692.   fhandle: Integer;                                { File handle }
  2693.     openbuf: TOFStruct;                            { Open file buffer }
  2694.   nb     : Integer;               { number of bytes to write }
  2695.   j      : Integer;
  2696.  
  2697. BEGIN
  2698.   gfName( fnum, s );
  2699.   fhandle := Openfile( @s, openbuf, of_Create);
  2700.  
  2701.   IF fhandle = -1 THEN
  2702.   BEGIN
  2703.       { Tell of failure }
  2704.  
  2705.     EXIT;
  2706.   END;
  2707.   nb := wvector[ fnum ];
  2708.   j := _lwrite( fhandle, BigFileBuff^, nb );
  2709.  
  2710.   IF j=-1 THEN
  2711.   BEGIN
  2712.     { Failed to write the file...tell user }
  2713.  
  2714.     _lclose(fhandle);
  2715.     Openfile( @s, openbuf, of_Delete);
  2716.     EXIT;
  2717.   END;
  2718.   myMax := myMax + nb;
  2719.  
  2720.   _lclose( fhandle );
  2721. END;
  2722.  
  2723.  
  2724.  
  2725. {********************
  2726. ** Delete all files from random file i/o test.
  2727. *}
  2728. PROCEDURE DeleteAllFiles;
  2729. VAR
  2730.   i: INTEGER;
  2731.   s: FileName;
  2732.   fhandle: Integer;                                { File handle }
  2733.     openbuf: TOFStruct;                            { Open file buffer }
  2734.  
  2735. BEGIN
  2736.   FOR i := 0 to 19
  2737.   do begin
  2738.     gfName( i, s );
  2739.     fhandle := Openfile( @s, openbuf, of_Delete );
  2740.   end;
  2741.  
  2742.  
  2743. END;
  2744.  
  2745.  
  2746. {** Opens a file and appends the appropriate number of bytes.
  2747.  **
  2748.  **}
  2749. PROCEDURE appendFiles( fnum:integer; VAR myMax: LongInt );
  2750. CONST
  2751.    wvector: ARRAY[0..19] of LongInt = ( 1200, 2030, 31111, 3400, 9099,
  2752.                                         2075, 7000,   400, 2200, 2700,
  2753.                                         2360, 1495,  5960, 3430,   70,
  2754.                                         3600, 8900,  1233, 4000, 1000 );
  2755. VAR
  2756.   i: INTEGER;
  2757.   s: FileName;
  2758.   fhandle: Integer;                                { File handle }
  2759.     openbuf: TOFStruct;                            { Open file buffer }
  2760.   nb     : Integer;               { number of bytes to write }
  2761.   j      : Integer;
  2762.  
  2763. BEGIN
  2764.   gfName( fnum, s );
  2765.   fhandle := OpenFile( s, openbuf, of_Write );
  2766.   _llseek( fhandle, 0, 2 );        { seek to end of file}
  2767.   nb := wvector[ fnum ];
  2768.   j:=_lwrite( fhandle, BigFileBuff^, nb );
  2769.   myMax := myMax + nb;
  2770.   _lclose( fHandle );
  2771.  
  2772. END;
  2773.  
  2774.  
  2775. {********************
  2776. ** FileSize
  2777. ** Determine the size of an already-open file.
  2778. *}
  2779. FUNCTION FileSize( fh: Integer ) : LongInt;
  2780. VAR
  2781.   pos:  LongInt;
  2782. BEGIN
  2783.   Pos := _llseek( fh, 0, 1 );           { get current file position }
  2784.   FileSize := _llseek( fh, 0, 2 );      { seek to end of file -- return new position }
  2785.   _llseek( fh, Pos, 0 );                { seek back to original position }
  2786. END; {FileSize}
  2787.  
  2788.  
  2789.  
  2790. {*********************
  2791. ** ll_seekwrite
  2792. **   seek to offset from beginning of file.
  2793. **   then write nb bytes from the global buffer
  2794. *}
  2795. PROCEDURE ll_seekwrite( fh:Integer; offset:LongInt; nb:LongInt );
  2796.  
  2797. BEGIN
  2798.   _llseek( fh, offset, 0 );
  2799.   _lwrite(fh, BigFileBuff^, nb );
  2800. END;
  2801.  
  2802.  
  2803. {*********************
  2804. ** ll_seekread
  2805. **   seek to offset from beginning of file.
  2806. **   then read nb bytes from the global buffer
  2807. *}
  2808. PROCEDURE ll_seekread( fh: Integer; offset: LongInt; nb: LongInt );
  2809.  
  2810. BEGIN
  2811.   _llseek( fh, offset, 0 );
  2812.   _lread( fh, BigFileBuff^, nb );
  2813. END;
  2814.  
  2815.  
  2816. (********************
  2817. ** Random file I/O
  2818. *)
  2819. PROCEDURE RFile_IO( doTime: LongInt );
  2820. CONST
  2821. MaxRandomIOBytes = 10000000;     { don't exceed 10 Mbytes of output }
  2822.  
  2823. VAR
  2824.   fileResult: Boolean;
  2825.   l         : LongInt;
  2826.   i         : Integer;
  2827.   myMax     : LongInt;              { how many bytes of throughput? }
  2828.   avg       : LongInt;              { number of bytes read on a cycle }
  2829.   n         : Integer;
  2830.   nb        : LongInt;              { number of bytes to read/write }
  2831.   fh        : Integer;              { file handle }
  2832.   str       : FileName;             { full filename }
  2833.   flen      : LongInt;              { file length }
  2834.   offset    : LongInt;              { offset into file }
  2835.   count     : Integer;              { debugging counter }
  2836.   rbytes    : LongInt;              { number of bytes read }
  2837.   wbytes    : LongInt;              { number of bytes written }
  2838.   outstr:  Array [0..80] of Char; { message to display }
  2839.   outstrlen: Integer;             { need to know how long it is }
  2840.  
  2841. BEGIN
  2842.  
  2843.     { See if we have enough free space.  If not, bail
  2844.     out.  We set our minimum to 6 MB }
  2845.  
  2846.     InitBenchDisplay;
  2847.   
  2848.   strPCopy( @outstr, 'Starting random file i/o test.');
  2849.   outstrlen := StrLen( @outstr );
  2850.   DisplayBenchLine( @outstr, outstrlen );
  2851.   
  2852.   { create the global buffer }
  2853.   New( BigFileBuff );        {rgac? fix possible run-time}
  2854.  
  2855.   { initialize the global buffer }
  2856.   for l:= 0 to 39999
  2857.   do begin
  2858.     BigFileBuff^[l] := 'A';
  2859.   end;
  2860.  
  2861.   { Initialize the maximum }
  2862.   myMax := 0;
  2863.  
  2864.  
  2865.   StrPCopy( @outstr, 'Creating test files.');
  2866.   outstrlen := StrLen( @outstr );
  2867.   DisplayBenchLine( @outstr, outstrlen );
  2868.  
  2869.   { create the files }
  2870.   for i:= 0 to 19
  2871.   do begin
  2872.     createFiles( i, myMax );
  2873.   end;
  2874.  
  2875.   { extend the files }
  2876.   for i := 0 to 19
  2877.   do begin
  2878.     appendFiles( i, myMax );
  2879.   end;
  2880.  
  2881.   myMax := 0;
  2882.   { initialize random number generator and misc variables }
  2883.   Randnum(13);
  2884.   elapsedtsecarray[rfio_test_id] := 0;
  2885.   iterarray[rfio_test_id] := 1;
  2886.   avg := 0;
  2887.   rbytes := 0;
  2888.   wbytes := 0;
  2889.  
  2890.  
  2891.   DelaySeconds( 5 );                  { let buffers catch up from last test }
  2892.   StrPCopy( @outstr, 'Starting Test:');
  2893.   outstrlen := StrLen( @outstr );
  2894.   DisplayBenchLine( @outstr, outstrlen );
  2895.  
  2896.   count := 0;
  2897.   { run the test }
  2898.   { for each pass, do 3 reads and 1 write }
  2899.   repeat
  2900.     avg := 0;
  2901.  
  2902.     for i := 0 to 2
  2903.     do begin
  2904.       n := Abs( GetRandWithCeiling(19) );
  2905.       gfName( n, str );
  2906.       fh := _lopen( str, of_Read );
  2907.       flen := fileSize( fh );
  2908.       offset := Abs( GetRandWithCeiling( flen ) );
  2909.       flen := flen - offset;
  2910.       if( flen <= 0 )
  2911.       then begin
  2912.         flen := 1;
  2913.       end;
  2914.  
  2915.       if( flen > 32000 ) then
  2916.         begin
  2917.           nb := 32000;
  2918.         end else
  2919.         begin
  2920.           nb := flen;
  2921.         end;
  2922.  
  2923.       nb := Abs( GetRandWithCeiling( nb ) );
  2924.  
  2925.       { AHA! the actual test! }
  2926.  
  2927.       StartStopWatch;
  2928.       ll_seekread( fh, offset, nb );
  2929.       StopStopWatch;
  2930.  
  2931.       { accumulate the timing information }
  2932.       AccumTiming( rfio_test_id );
  2933.       avg := avg + nb;
  2934.       rbytes := rbytes + nb;
  2935.  
  2936.       { close the file -- we're done }
  2937.       _lclose( fh );
  2938.  
  2939.     end; {for loop}
  2940.  
  2941.     n := Abs( GetRandWithCeiling( 19 ) );
  2942.     n := Abs( GetRandWithCeiling( 19 ) );
  2943.     gfName( n, str );
  2944.     fh := _lopen( str, of_Write );
  2945.     flen := fileSize( fh );
  2946.     offset := Abs( GetRandWithCeiling( flen ) );
  2947.     nb := Trunc(avg / 3);
  2948.     if( offset + nb > flen )
  2949.     then begin
  2950.      myMax := myMax + offset + nb - flen;
  2951.      if( myMax > MaxRandomIOBytes )
  2952.      then begin
  2953.        exit
  2954.      end;
  2955.     end;
  2956.  
  2957.     StartStopWatch;
  2958.     ll_seekwrite( fh, offset, nb );
  2959.     StopStopWatch;
  2960.     AccumTiming( rfio_test_id );
  2961.     wbytes := wbytes + nb;
  2962.  
  2963.     _lclose( fh );
  2964.  
  2965.     Inc(count);
  2966.  
  2967.   until( elapsedtsecarray[ rfio_test_id ] > doTime );
  2968.  
  2969.    totalRandomIOBytes := rbytes + wbytes;
  2970.  
  2971.   { the tests are over, clean up the mess we've left }
  2972.  
  2973.   StrPCopy( @outstr, 'Deleting Files.');
  2974.   outstrlen := StrLen( @outstr );
  2975.   DisplayBenchLine( @outstr, outstrlen );
  2976.  
  2977.  
  2978.   { zap the files }
  2979.   DeleteAllFiles;
  2980.   {zap the memory }
  2981.   Dispose( BigFileBuff );
  2982. END;
  2983.  
  2984.  
  2985.  
  2986. {***************************
  2987. ** Add logfile header to output
  2988. **
  2989. ** If toFile is true -- just send the data the log file.
  2990. ** If tofile is false -- just send the data to the screen.
  2991. ** n.b. We never send the information to both places.
  2992. *}
  2993. PROCEDURE logfileHeader( toFile: Boolean );
  2994. VAR
  2995.   outstr:   Array [0..81] of Char;
  2996.   tempstr:  Array [0..81] of Char;
  2997.   theHDC:   HDC;
  2998.   outlen:   Integer;
  2999.   tempWord: Word;
  3000.   tempInt:  Integer;
  3001.   tempLInt: LongInt;
  3002.   tempLInt2:LongInt;
  3003.   year  :   Word;
  3004.   month :   Word;
  3005.   day   :   Word;
  3006.   doweek:   Word;
  3007.   hour  :   Word;
  3008.   minute:   Word;
  3009.   second:   Word;
  3010.   sec100:   Word;
  3011.  
  3012. BEGIN
  3013.      StrCopy( outstr, 'File:        ' );
  3014.      StrPCopy( tempstr, logFileName );
  3015.      StrCat(  outstr, tempstr );
  3016.      if toFile
  3017.      then begin
  3018.        Writeln( logFile, outstr );
  3019.      end
  3020.      else begin
  3021.        outLen := StrLen( outstr );
  3022.        DisplayBenchLine( outstr, outLen );
  3023.      end;
  3024.  
  3025.      GetDate( year, month, day, doweek );
  3026.      StrCopy( outstr, 'Test run on: '  );
  3027.      Str( month, tempstr );
  3028.      StrCat( tempstr, '/' );
  3029.      StrCat( outstr, tempstr );
  3030.      Str( day, tempstr );
  3031.      StrCat( tempstr, '/' );
  3032.      StrCat( outstr, tempstr );
  3033.      Str( year, tempstr );
  3034.      StrCat( outstr, tempstr );
  3035.      StrCat( outstr, ' at: ' );
  3036.  
  3037.      GetTime( hour, minute, second, sec100 );
  3038.      Str( hour, tempstr );
  3039.      StrCat( outstr, tempstr );
  3040.      StrCat( outstr, ':' );
  3041.      if( minute < 10 )
  3042.      then begin
  3043.        StrCat( outstr, '0' );
  3044.      end;
  3045.      Str( minute, tempstr );
  3046.      StrCat( outstr, tempstr );
  3047.      if toFile
  3048.      then begin
  3049.        Writeln( logFile, outstr );
  3050.      end
  3051.      else begin
  3052.        outLen := StrLen( outstr );
  3053.        DisplayBenchLine( outstr, outLen );
  3054.      end;
  3055.  
  3056.      tempWord := GetVersion;
  3057.      StrCopy( outstr, 'Windows Version: ' );
  3058.      Str( Lo(tempWord), tempstr );
  3059.      StrCat( outstr, tempstr );
  3060.      StrCat( outstr, '.' );
  3061.      Str( Hi(tempWord), tempstr);
  3062.      StrCat( outstr, tempstr );
  3063.      if toFile
  3064.      then begin
  3065.        Writeln( logFile, outstr );
  3066.      end
  3067.      else begin
  3068.        outLen := StrLen( outstr );
  3069.        DisplayBenchLine( outstr, outLen );
  3070.      end;
  3071.  
  3072.      tempInt := GetSystemMetrics( sm_Debug );
  3073.      StrCopy( outstr, 'Debug version of Windows is ' );
  3074.      if( 0 = tempInt )
  3075.      then StrCat( outstr, 'not ' );
  3076.      StrCat( outstr, 'installed.' );
  3077.      if toFile
  3078.      then begin
  3079.        Writeln( logFile, outstr );
  3080.      end
  3081.      else begin
  3082.        outLen := StrLen( outstr );
  3083.        DisplayBenchLine( outstr, outLen );
  3084.      end;
  3085.  
  3086.      StrCopy( outstr, 'Screen width is: ' );
  3087.      tempInt := GetSystemMetrics( sm_CXScreen );
  3088.      Str( tempInt, tempStr );
  3089.      StrCat( outstr, tempStr );
  3090.      StrCat( outstr, ' pixels wide by ' );
  3091.      tempInt := GetSystemMetrics( sm_CYScreen );
  3092.      Str( tempInt, tempStr );
  3093.      StrCat( outstr, tempStr );
  3094.      StrCat( outstr, ' pixels high.' );
  3095.      if toFile
  3096.      then begin
  3097.        Writeln( logFile, outstr );
  3098.      end
  3099.      else begin
  3100.        outLen := StrLen( outstr );
  3101.        DisplayBenchLine( outstr, outLen );
  3102.      end;
  3103.  
  3104.      
  3105.      tempLInt := GlobalCompact( 0 );
  3106.      tempLInt := templint div 1024;
  3107.      Str( tempLInt, outstr );
  3108.      StrCat( outstr, ' Kbytes free in global heap.' );
  3109.      if toFile
  3110.      then begin
  3111.        Writeln( logFile, outstr );
  3112.      end
  3113.      else begin
  3114.        outLen := StrLen( outstr );
  3115.        DisplayBenchLine( outstr, outLen );
  3116.      end;
  3117.  
  3118.  
  3119.       
  3120. {     theHDC := GetDC( HByteWin );
  3121.      tempInt := GetDeviceCaps( theHDC, BitsPixel );
  3122.      StrCopy( outstr, 'Bit depth is ' );
  3123.      Str( tempInt, tempstr );
  3124.      StrCat( outstr, tempstr );
  3125.      StrCat( outstr, ' bits per pixel.' );
  3126.  
  3127.      if toFile
  3128.      then begin
  3129.        Writeln( logFile, outstr );
  3130.      end
  3131.      else begin
  3132.        outLen := StrLen( outstr );
  3133.        DisplayBenchLine( outstr, outLen );
  3134.      end;
  3135. why is bit depth 1 pixel? }
  3136.  
  3137. END;
  3138.  
  3139.  
  3140. (***************************
  3141. ** Display benchmark results
  3142. **
  3143. ** doLog indicates whether the information should be written to the named file.
  3144. ** oldResults indicates whether we show currently selected tests, or all tests
  3145. ** with results.
  3146. ** n.b. test results are not cleared between passes.
  3147. ****************************)
  3148.  
  3149. PROCEDURE DisplayResults( doLog : Boolean; oldResults : Boolean );
  3150. VAR
  3151.     i: Integer;                                                { Loop index }
  3152.   outstr: Array [0..80] of Char;        { Output string }
  3153.   outstrlen: Integer;                                { Output string length }
  3154.   valstr: Array [0..20] of Char;        { For holding values }
  3155.   numer: Real;                                            { Used in calculations }
  3156.   denom: Real;                                            { Same as above }
  3157.   result: Real;                                            { Results figure }
  3158.     dtemp: Real;                                            { For temporary results }
  3159.  
  3160. BEGIN
  3161.  
  3162.   if( doLog )                       { do we want to output to logfile? }
  3163.   then begin
  3164.     Assign( logFile, logFileName );
  3165.     Rewrite( logfile );
  3166.     logfileHeader(TRUE);
  3167.   end;
  3168.  
  3169.   InitBenchDisplay;
  3170.  
  3171.   StrCopy( outstr, '   TEST RESULTS' );
  3172.   outstrlen := StrLen( outstr );
  3173.   DisplayBenchLine( outstr, outstrlen );
  3174.  
  3175.     { Examine the do_test_flags[] array to determine which tests
  3176.     were executed.  Produce a line of text for each one. }
  3177.     FOR i:=1 TO max_num_tests DO
  3178.   BEGIN
  3179.     StrPCopy( @outstr, '' );
  3180.       IF ( TRUE = do_test_flags[i] ) OR (TRUE = oldResults)
  3181.     THEN BEGIN
  3182.  
  3183.       { only process tests for which time has elapsed.
  3184.         takes care of showing old test results which have not actually been run!
  3185.       }
  3186.       if( elapsedtsecarray[i] > 0 )
  3187.       then begin
  3188.  
  3189.  
  3190.           { Begin building the output string. }
  3191.         StrPCopy(@outstr,test_name[i]);
  3192.               numer:=iterarray[i];
  3193.         denom:=elapsedtsecarray[i];
  3194.         result := 0;                  {consider the case where denom is 0}
  3195.         if( denom > 0 )
  3196.         then begin
  3197.           result:=( numer/denom) * 1000;
  3198.         end;
  3199.       
  3200.               CASE i OF
  3201.                   pixel_test_id:
  3202.                       BEGIN
  3203.                 dtemp:=pixels_per_iter;
  3204.               result:=result * dtemp;        { Pixels per second }
  3205.               Str(result:10:2,valstr);
  3206.               StrCat(@outstr,@valstr);
  3207.               StrCat(@outstr,' pix per sec')
  3208.                       END;
  3209.  
  3210.                   line_test_id:
  3211.                     BEGIN
  3212.               dtemp:=lines_per_iter;
  3213.             result:=result * dtemp;        { Lines per second }
  3214.                         Str(result:10:2,valstr);
  3215.             StrCat(@outstr,@valstr);
  3216.             StrCat(@outstr,' lines per sec');
  3217.                     END;
  3218.  
  3219.                   rect_test_id:
  3220.                       BEGIN
  3221.                           dtemp:=rects_per_iter;
  3222.               result:=result * dtemp;        { Rectangles per second }
  3223.               Str(result:10:2,valstr);
  3224.               StrCat(@outstr,@valstr);
  3225.               StrCat(@outstr,' rects per sec');
  3226.                       END;
  3227.  
  3228.                    poly_test_id:
  3229.                       BEGIN
  3230.                           dtemp:=polys_per_iter;
  3231.               result:=result * dtemp;        { Polygons per second }
  3232.               Str(result:10:2,valstr);
  3233.               StrCat(@outstr,@valstr);
  3234.               StrCat(@outstr,' polys per sec');
  3235.                       END;
  3236.  
  3237.                   arce_test_id:
  3238.                       BEGIN
  3239.                 dtemp:=ellps_per_iter;
  3240.               result:=result * dtemp;        { Ellipses per second }
  3241.               Str(result:10:2,valstr);
  3242.               StrCat(@outstr,@valstr);
  3243.               StrCat(@outstr,' ellps per sec');
  3244.                       END;
  3245.  
  3246.                   bitblt_test_id:
  3247.                       BEGIN
  3248.                 dtemp:=bmap_points;
  3249.               result:=result * dtemp;        { Bitblt ops per second }
  3250.               Str(result:10:2,valstr);
  3251.               StrCat(@outstr,@valstr);
  3252.               StrCat(@outstr,' bitblts per sec');
  3253.                       END;
  3254.  
  3255.                   lmem_test_id:
  3256.                       BEGIN
  3257.               dtemp := iterarray[lmem_test_id];
  3258.               result := dtemp / elapsedtsecarray[lmem_test_id];  {ms}
  3259.               result := result * 1000;                           {sec}
  3260.               Str( result:10:2, valstr );
  3261.               StrCat( @outstr, @valstr );
  3262.               StrCat( @outstr, ' iterations per sec' );
  3263.                       END;
  3264.  
  3265.                   gmem_test_id:
  3266.                       BEGIN
  3267.               dtemp := iterarray[gmem_test_id];
  3268.               result := dtemp / elapsedtsecarray[gmem_test_id];  {ms}
  3269.               result := result * 1000;                           {sec}
  3270.               Str( result:10:2, valstr );
  3271.               StrCat( @outstr, @valstr );
  3272.               StrCat( @outstr, ' iterations per sec' );
  3273.                       END;
  3274.  
  3275.                   sfio_test_id:
  3276.                       BEGIN
  3277.               dtemp := (sfio_bytes_per_iter * numer) / 1024;  {bytes -> Kbytes}
  3278.               result := dtemp * result;                       {Kbytes / second}
  3279.               Str( result:10:2, valstr );
  3280.               StrCat( @outstr, @valstr );
  3281.               StrCat( @outstr, ' Kbytes per sec' );
  3282.                       END;
  3283.  
  3284.                     rfio_test_id:
  3285.                       BEGIN
  3286.               dtemp := (totalRandomIoBytes * result) / 1024;
  3287.               Str( dtemp:10:2, valstr );
  3288.               StrCat( @outstr, @valstr );
  3289.               StrCat( @outstr, ' Kbytes per sec' );
  3290.                       END;
  3291.  
  3292.                   texto_test_id:
  3293.                       BEGIN
  3294.                  dtemp:=text_per_iter;
  3295.               result:=result * dtemp;        { Textout lines per second }
  3296.               Str(result:10:2,valstr);
  3297.               StrCat(@outstr,@valstr);
  3298.               StrCat(@outstr,' TextOut ips   ');
  3299.             END;
  3300.  
  3301.           dtext_test_id:
  3302.               BEGIN
  3303.                  dtemp:=text_per_iter;
  3304.               result:=result * dtemp;        { Drawtext lines per second }
  3305.               Str(result:10:2,valstr);
  3306.               StrCat(@outstr,@valstr);
  3307.               StrCat(@outstr,' Drawtext ips');
  3308.                       END;
  3309.  
  3310.           END;  { CASE }
  3311.  
  3312.       { Display one line of results }
  3313.       outstrlen:=StrLen(@outstr);
  3314.       if( outstrlen  > 0 )
  3315.       then begin
  3316.         DisplayBenchLine(@outstr, outstrlen );
  3317.  
  3318.         { See if we also need to send to output file. }
  3319.         if( doLog )
  3320.         then begin
  3321.           Writeln( logFile, outstr );
  3322.         end;
  3323.       end; {string has content }
  3324.     END; { if time has elapsed }
  3325.    END;
  3326.    END; { FOR }
  3327.  
  3328.  
  3329.   CloseBenchDisplay;
  3330.  
  3331.   { close file if we were writing to one. }
  3332.   if( doLog )
  3333.   then begin
  3334.     Close( logFile );
  3335.   end;
  3336.  
  3337. END;    { DisplayResults }
  3338.  
  3339. (***************************************************
  3340.  ** Right justify a string.  This has the effect of
  3341.  ** padding the string on the left with blanks until
  3342.  ** the string fills out the field width.
  3343.  *)
  3344. PROCEDURE RightJustifyString( fieldwidth : Integer; strng : PChar);
  3345. VAR
  3346.     tempstr: ARRAY[0..60] of Char;
  3347.  
  3348. BEGIN
  3349.  
  3350.     { Add fieldwidth-length(strng) bytes to our
  3351.     temp string.  Note that if strng is already
  3352.     longer than fieldwidth, we gotta truncate. }
  3353.   tempstr[0]:=#0;
  3354.   IF fieldwidth-StrLen(strng) > 0 THEN
  3355.   BEGIN
  3356.       FillChar(tempstr[0],60,#0);
  3357.     FillChar(tempstr[0],fieldwidth-StrLen(strng),' ');
  3358.   END;
  3359.  
  3360.   { Now concatenate str to the end of tempstr, and
  3361.     move the results back into strng so it can go home. }
  3362.   StrCat(tempstr,strng);
  3363.   StrCopy(strng,tempstr);
  3364. END;    { RightJustifyString }
  3365.  
  3366. (************************************************************
  3367.  ** Fill out a string to n bytes.  Pads on right with blanks.
  3368.  ** This routine will also truncate if necessary.
  3369.  *)
  3370. PROCEDURE FillOutString( fieldwidth : Integer; strng: PChar ) ;
  3371. BEGIN
  3372.  
  3373.     { Attach fieldwidth-Length(string) blanks.
  3374.     Don't bother if that's a negative number or zero. }
  3375.   IF fieldwidth-StrLen(strng) > 0 THEN
  3376.       FillChar(strng[StrLen(strng)],fieldwidth-StrLen(strng),' ');
  3377.  
  3378.   strng[fieldwidth-1]:=#0;
  3379. END;    { FillOutstring }
  3380.  
  3381. (*************************************************
  3382.  ** Display a line of test comparison information.
  3383.  ** This routine determines whether the current line is
  3384.  ** greater than the starting line, but less than the
  3385.  ** ending line.  If so, the current line can be displayed.
  3386.  ** If not, then it simply updates the current line
  3387.  ** and returns without displaying anything.
  3388.  ** NOTE: This routine borrows the previously-defined
  3389.  **  routine DisplayBenchLine, which updates screen
  3390.  **  positions appropriately.
  3391.  *)
  3392. PROCEDURE DispCompTestLine( testnum: Integer; VAR currentline: Integer );
  3393. VAR
  3394.     lineotext: ARRAY[0..59] of Char;    { Line to output }
  3395.   tempstr: ARRAY[0..20] of Char;        { A temp. string }
  3396.   result: Real;                                            { Value from file }
  3397.   iterspersec: Real;                                { Iterations per second }
  3398.   i: Integer;                                                { Loop index }
  3399. BEGIN
  3400.     { Verify that the line we are about to display is in the
  3401.     active portion of the window. }
  3402.   IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
  3403.   BEGIN
  3404.   
  3405.         { Get the test name }
  3406.     StrPCopy(lineotext,test_name[testnum]);
  3407.       FillOutString(18,lineotext);
  3408.  
  3409.       { Attach the iterations per second from the comparison system }
  3410.     result:=fbptr^.testresult[testnum];
  3411.       Str(result:10:2,tempstr);
  3412.     RightJustifyString(10,tempstr);
  3413.     StrCat(lineotext,tempstr);
  3414.  
  3415.     { If we have no values for this test yet, then the
  3416.       rest of the line is ...well...blank. }
  3417.     IF (iterarray[testnum]=0) OR (elapsedtsecarray[testnum]=0) THEN
  3418.         StrCat(lineotext,'       --test not run--')
  3419.     ELSE
  3420.         BEGIN
  3421.               { Calculate the iterations per second }
  3422.               iterspersec:=iterarray[testnum];
  3423.               iterspersec:=iterspersec * items_per_iter[testnum]*1000;
  3424.               iterspersec:=iterspersec / elapsedtsecarray[testnum];
  3425.  
  3426.         { If the test is one of the file I/O tests, adjust for
  3427.           K bytes per second }
  3428.         IF (testnum=sfio_test_id) OR (testnum=rfio_test_id) THEN
  3429.             iterspersec:=iterspersec / 1024;
  3430.  
  3431.                 Str(iterspersec:10:2,tempstr);
  3432.  
  3433.               { Attach iterations per second to the line already built }
  3434.                  StrCat(lineotext,'     ');
  3435.             RightJustifyString(10,tempstr);
  3436.             StrCat(lineotext,tempstr);
  3437.  
  3438.               { Calculate the index }
  3439.               result:=iterspersec / fbptr^.testresult[testnum];
  3440.               Str(result:10:2,tempstr);
  3441.  
  3442.               { Attach the index }
  3443.         StrCat(lineotext,'     ');
  3444.             RightJustifyString(8,tempstr);
  3445.             StrCat(lineotext,tempstr);
  3446.         END;
  3447.  
  3448.       { Display it }
  3449.         DisplayBenchLine(lineotext,StrLen(lineotext));
  3450.     END;
  3451.     Inc(currentline);            { Increment the current line }
  3452.  
  3453. END;    { DispCompTestLine }
  3454.  
  3455. (*******************************************
  3456.  ** Display benchmark comparison information
  3457.  ** This is handled within a simple dialog box with a
  3458.  ** scroll bar and an EXIT button.
  3459.  *)
  3460. FUNCTION BenchCompDialog(Dialog: HWnd; Message,  WParam: Word ;
  3461.     LParam: LongInt): Bool; export;
  3462.  
  3463. VAR
  3464.     HDlgDC:    HDC;                                                { Device context }
  3465.     systemname:    ARRAY [0..70] of Char;    { Name of system }
  3466.   compdispline: ARRAY [0..80] of Char;  { Display line string }
  3467.   i:                    Integer;                                { Index }
  3468.   j:                    Integer;                                { Another index }
  3469.   currentline: Integer;                                { Current line on display }
  3470.   DlgPntStruct:    TPaintStruct;                    { Paint struct for dialog }
  3471.   tempreal:        Real;                                        { Temporary real }
  3472.   doInvalid:    Bool;                                        { Flag to invalidate rect }
  3473.   syscoloridx: ARRAY [0..0] of Integer;
  3474.   syscolorval: ARRAY [0..0] of Longint;
  3475. BEGIN
  3476.  
  3477. CASE Message OF
  3478.  
  3479.     wm_InitDialog:
  3480.     BEGIN
  3481.  
  3482.     { Grab the client rectangle area and place it into a global.
  3483.       Decrement the bottom by a certain amount to allow
  3484.       room for the button.  We can use this for calculating the
  3485.       number of displayable lines. }
  3486.     GetClientRect(Dialog,bcDispRect);
  3487.     bcDispRect.top:=bcDispRect.top+ansiffontheight;
  3488.         bcDispRect.bottom:=bcDispRect.bottom-(2*ansiffontheight);
  3489.     benchlineHDCheight:=bcDispRect.bottom-bcDispRect.top;
  3490.     bcNumLines:=(benchlineHDCheight DIV sysfontheight)-2;
  3491.  
  3492.       { Get to the beginning of the file }
  3493.       Reset(DataFile);
  3494.  
  3495.       { Read a bunch of data from the file until we've read it all }
  3496.       i:=1;
  3497.       REPEAT
  3498.           { Read in the system description.  If it's first character is
  3499.           an asterisk, we presume we've hit the end of the list
  3500.           and we're done. }
  3501.         READLN(DataFile,systemname);
  3502.         IF systemname[0]<>'*' THEN
  3503.         BEGIN
  3504.  
  3505.           { Allocate some memory for this guy }
  3506.         fbhand[i]:=GlobalAlloc(GMEM_MOVEABLE OR GMEM_NODISCARD,SizeOf(CompData));
  3507.         fbptr:=GlobalLock(fbhand[i]);
  3508.  
  3509.         StrCopy(fbptr^.description,systemname);
  3510.  
  3511.         { Read in system name }
  3512.         READLN(DataFile,systemname);
  3513.         StrCopy(fbptr^.sysname,systemname);
  3514.  
  3515.           { Read in the test results. }
  3516.         FOR j:= 1 TO max_test_id DO
  3517.             BEGIN
  3518.                 READLN(DataFile,tempreal);
  3519.               fbptr^.testresult[j]:=tempreal;
  3520.           END;
  3521.  
  3522.         { Unlock this handle so the global heap can
  3523.             compact if it needs to. }
  3524.         GlobalUnlock(fbhand[i]);
  3525.  
  3526.           Inc(i);                    { Advance to next handle }
  3527.  
  3528.         END;
  3529.       UNTIL systemname[0]='*';
  3530.  
  3531.     bcNumSystems:=i-1;        { # of systems in the table }
  3532.  
  3533.     { Calculate the total # of lines in the display.  Use
  3534.       this to set the range of the scrollbar. }
  3535.     bcTotNumLines:= 2+bcNumSystems * (4+max_num_tests);
  3536.  
  3537.     { Set scrollbar range and initialize it }
  3538.     SetScrollRange(Dialog,sb_VERT,1,bcTotNumLines,FALSE);
  3539.     SetScrollPos(Dialog,sb_VERT,1,TRUE);
  3540.         bcBeginLine:=1;
  3541.  
  3542.     { Set the focus }
  3543.         SetFocus(GetDlgItem(Dialog,IDB_OK));
  3544.  
  3545.     { Initialize screen coordinate stuff to make the
  3546.       DisplayBenchLine routine happy. }
  3547.       BenchLineHDC := GetDC( Dialog );
  3548.       BenchLineX   := 10;
  3549.  
  3550.       { Set us up with a fixed pitch font }
  3551.       SelectObject( BenchLineHDC, GetStockObject(ANSI_Fixed_Font) );
  3552.  
  3553.       BenchLineY := ansiffontheight;
  3554.       BenchLineYInc:= ansiffontheight;
  3555.  
  3556.     { Get old background color }
  3557.     oldwinbkcolor:=GetSysColor(color_Window);
  3558.  
  3559.       { Set foreground and background colors }
  3560.     syscoloridx[0]:=color_Window;
  3561.     syscolorval[0]:=RGB(255,255,255);
  3562.     SetSysColors(1,syscoloridx,syscolorval);
  3563.       SetTextColor( BenchLineHDC, RGB(0,0,0) );
  3564.     SetBkColor(BenchLineHDC,RGB(255,255,255));
  3565.     SetBkMode(BenchLineHDC,Opaque);
  3566.  
  3567.     END;    { wm_InitDialog }
  3568.  
  3569.   wm_VScroll:
  3570.       BEGIN
  3571.     doInvalid:=FALSE;
  3572.       CASE WParam OF
  3573.             { NOTE: In the scrolling stuff, the variable bcBeginLine
  3574.           indicates which line is at the top of the display
  3575.         box.  We calculate everything else based on bcBeginLine. }
  3576.  
  3577.         sb_Top:
  3578.           BEGIN
  3579.             bcBeginLine:=1;
  3580.           doInvalid:=TRUE;
  3581.         END;
  3582.  
  3583.       sb_Bottom:
  3584.           BEGIN
  3585.                     bcBeginLine:=bcTotNumLines-1;
  3586.           doInvalid:=TRUE;
  3587.         END;
  3588.  
  3589.       sb_LineUp:
  3590.           BEGIN
  3591.             IF bcBeginLine>1 THEN
  3592.               bcBeginLine:=bcBeginLine-1;
  3593.           doInvalid:=TRUE;
  3594.         END;
  3595.  
  3596.       sb_LineDown:
  3597.           BEGIN
  3598.             IF bcBeginLine<(bcTotNumLines-1) THEN
  3599.               bcBeginLine:=bcBeginLine+1;
  3600.           doInvalid:=TRUE;
  3601.         END;
  3602.  
  3603.       sb_PageUp:
  3604.           BEGIN
  3605.             bcBeginLine:=bcBeginLine-5;
  3606.           IF bcBeginLine<1 THEN bcBeginLine:=1;
  3607.           doInvalid:=TRUE;
  3608.         END;
  3609.  
  3610.       sb_PageDown:
  3611.           BEGIN
  3612.             bcBeginLine:=bcBeginLine+5;
  3613.           IF bcBeginLine>(bcTotNumLines-1) THEN
  3614.               bcBeginLine:=bcTotNumLines-1;
  3615.           doInvalid:=TRUE;
  3616.         END;
  3617.  
  3618.       sb_ThumbPosition:
  3619.           BEGIN
  3620.             bcBeginLine:=WordRec(LParam).lo;
  3621.           doInvalid:=TRUE;
  3622.         END;
  3623.  
  3624.     END;    { CASE WParam }
  3625.  
  3626.     SetScrollPos(Dialog,sb_VERT,bcBeginLine,TRUE);
  3627.     IF doInvalid THEN
  3628.         InvalidateRect(Dialog,@bcDispRect,TRUE);
  3629.  
  3630.     END;        { CASE wm_Vscroll }
  3631.  
  3632.   wm_Paint:
  3633.   BEGIN
  3634.  
  3635.       { Clear the display area }
  3636.     HDlgDC:=BeginPaint(Dialog,DlgPntStruct);
  3637.  
  3638.       { Initialize the cursor position }
  3639.       currentline:=1;            { Start a line counter }
  3640.     benchLineY:=sysfontheight;
  3641.  
  3642.     i:=1;                                { i counts # of systems }
  3643.     REPEAT
  3644.         { Lock the handle...resolving to pointer }
  3645.       fbptr:=GlobalLock(fbhand[i]);
  3646.  
  3647.           IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
  3648.           DisplayBenchLine(fbptr^.description,StrLen(fbptr^.description));
  3649.  
  3650.       { See if the heading line is displayable.  If so,
  3651.         build it and display it. }
  3652.           IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
  3653.       BEGIN
  3654.           StrCopy(compdispline,'  Test            ');
  3655.         StrCopy(systemname,fbptr^.sysname);
  3656.         FillOutString(18,systemname);
  3657.         StrCat(compdispline,systemname);
  3658.         StrCat(compdispline,' This System      Index');
  3659.           DisplayBenchLine(compdispline,StrLen(compdispline));
  3660.       END;
  3661.       Inc(currentline);
  3662.  
  3663.       { Display dashed line }
  3664.           IF (currentline>=bcBeginLine) AND (benchLineY<benchLineHDCheight) THEN
  3665.           DisplayBenchLine(dashstr,60);
  3666.       Inc(currentline);
  3667.  
  3668.             { Display a line per test }
  3669.       FOR j:=1 TO max_test_id DO
  3670.                 DispCompTestLine(j,currentline);
  3671.  
  3672.       { Display a blank line }
  3673.       StrCopy(compdispline,'  ');
  3674.       DisplayBenchLine(compdispline,StrLen(compdispline));
  3675.  
  3676.       { Display complete for that system. Unlock the handle. }
  3677.       GlobalUnlock(fbhand[i]);
  3678.  
  3679.       Inc(i);                    { Increment system # }
  3680.  
  3681.     UNTIL ((i-1)=bcNumSystems) OR (benchLineY>BenchLineHDCheight);
  3682.     EndPaint(Dialog,DlgPntStruct);
  3683.  
  3684.   END;    { wm_Paint }
  3685.  
  3686.   wm_Command:
  3687.   BEGIN
  3688.       CASE WParam OF
  3689.         IDB_OK:                    { User pushed Exit button }
  3690.       BEGIN
  3691.               { Get rid of all the handles we allocated. }
  3692.             FOR i:=0 to (bcNumSystems-1) DO
  3693.             BEGIN
  3694.                 GlobalUnlock(fbhand[i]);
  3695.               GlobalFree(fbhand[i]);
  3696.             END;
  3697.                 ReleaseDC(Dialog,BenchLineHDC);
  3698.         EndDialog(Dialog,NULL);
  3699.               BenchCompDialog:=TRUE;
  3700.              syscolorval[0]:=oldwinbkcolor;
  3701.             syscoloridx[0]:=color_Window;
  3702.             SetSysColors(1,syscoloridx,syscolorval);
  3703.         Exit;
  3704.       END;    { IDB_OK }
  3705.     END;        { CASE WParam }
  3706.   END;            { wm_Command }
  3707.  
  3708. END;                { CASE Message }
  3709.  
  3710.   BenchCompDialog:=FALSE;
  3711. END;    {  BenchCompDialog }
  3712.  
  3713. (******************************************************
  3714.  ** DiskSpaceAlert
  3715.  ** This procedure throws up the alert that tells the
  3716.  ** guy he doesn't have enough disk space to run the
  3717.  ** disk space test.
  3718.  *)
  3719. PROCEDURE DiskSpaceAlert;
  3720. VAR
  3721.     dlgproc: TFarProc;        { Procedure instance }
  3722.  
  3723. BEGIN
  3724.     ShowCursor(TRUE);
  3725.     ADTx:=28;
  3726.   ADTy:=20;
  3727.   StrCopy(@AlertDlgText,'Disk tests require 6 MB of free disk space');
  3728.     ADTCount:=StrLen(@AlertDlgText);
  3729.   dlgproc:=MakeProcInstance(@StandardalertDialog,HInstance);
  3730.   DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
  3731.   FreeProcInstance(dlgproc);
  3732.   ShowCursor(FALSE);
  3733. END;    { DiskSpaceAlert }
  3734.  
  3735. (*********************************************************
  3736.  ** Execute the benchmarks selected and record the results
  3737.  ** in the proper places.
  3738.  *)
  3739. PROCEDURE DoTests;
  3740. VAR
  3741.     i: Integer;                        { Loop index }
  3742. BEGIN
  3743.  
  3744.     { Turn the cursor off }
  3745.   ShowCursor(FALSE);
  3746.  
  3747.  
  3748.   FOR i := 1 TO max_num_tests DO
  3749.       IF do_test_flags[i] THEN
  3750.         BEGIN
  3751.  
  3752.             CASE i OF
  3753.                 pixel_test_id:
  3754.                     BEGIN
  3755.                         PixelTest;
  3756.                     END;
  3757.  
  3758.                 line_test_id:
  3759.                     BEGIN
  3760.                         LineTest;
  3761.                     END;
  3762.  
  3763.                 rect_test_id:
  3764.                     BEGIN
  3765.                         RectTest;
  3766.                     END;
  3767.  
  3768.                 poly_test_id:
  3769.                     BEGIN
  3770.                         PolygonTest;
  3771.                     END;
  3772.  
  3773.                 arce_test_id:
  3774.                     BEGIN
  3775.               EllipseTest;
  3776.                     END;
  3777.  
  3778.                 bitblt_test_id:
  3779.                     BEGIN
  3780.               BitbltTest;
  3781.                     END;
  3782.  
  3783.                 lmem_test_id:
  3784.                     BEGIN
  3785.               LMemTest;
  3786.                     END;
  3787.  
  3788.                 gmem_test_id:
  3789.                     BEGIN
  3790.               GMemTest;
  3791.                     END;
  3792.  
  3793.                 sfio_test_id:
  3794.                     BEGIN
  3795.               { Make sure we have enough space }
  3796.               IF DiskFree(0)<disk_space_needed THEN
  3797.                 DiskSpaceAlert
  3798.             ELSE
  3799.                sfile_io;
  3800.                     END;
  3801.  
  3802.                 rfio_test_id:
  3803.                     BEGIN
  3804.               IF DiskFree(0)<disk_space_needed THEN
  3805.                 DiskSpaceAlert
  3806.             ELSE
  3807.                 rfile_io( rfile_io_secs * 1000); {test works in milliseconds}
  3808.                     END;
  3809.  
  3810.                 texto_test_id:
  3811.                     BEGIN
  3812.               TextTest;
  3813.                     END;
  3814.         END;  { CASE }
  3815.   END;        { FOR }
  3816.  
  3817.   someTests := TRUE;
  3818.   { Turn cursor back on }
  3819.   ShowCursor(TRUE);
  3820.  
  3821. END; { DoTests }
  3822.  
  3823. { **************************** }
  3824. { ** MENU HANDLING ROUTINES ** }
  3825. { **************************** }
  3826. PROCEDURE MainMenuProc(WParam: WORD);
  3827. VAR
  3828.     dlgproc: TFarProc;        { Procedure instance }
  3829.  
  3830. BEGIN
  3831. CASE WParam OF
  3832.  
  3833.     IDM_SETLOG:               { ** Set Log File ** }
  3834.         { Display file dialog allowing user to select a log file }
  3835.         BEGIN
  3836.         dlgproc:=MakeProcInstance(@GetLogNameDialogAction,HInstance);
  3837.       DialogBox(HInstance,'GETLOGDIALOG',HByteWin,dlgproc);
  3838.       FreeProcInstance(dlgproc);
  3839.         END;
  3840.  
  3841.     IDM_DISPLOG:              { ** Display Log File ** }
  3842.     { Display current log information }
  3843.         BEGIN
  3844.       if( someTests )
  3845.       then begin
  3846.         displayResults( TRUE, TRUE );  { show results on screen, write to file }
  3847.       end;
  3848.         END;
  3849.  
  3850.     IDM_EXIT:                 { ** Exit the program ** }
  3851.         BEGIN
  3852.         SendMessage(HByteWin,wm_Close,0,0);
  3853.       Exit;
  3854.         END;
  3855.  
  3856.   IDM_INFO:                                    { ** About box ** }
  3857.       BEGIN
  3858.         ADTCount:=-1;                    { Alert dialog...display byte logo }
  3859.         dlgproc:=MakeProcInstance(@StandardAlertDialog,HInstance);
  3860.       DialogBox(HInstance,'ABOUTDLG',HByteWin,dlgproc);
  3861.       FreeProcInstance(dlgproc);
  3862.     END;
  3863.  
  3864.     IDM_CONFBENCHES:          { ** Configure benchmarks ** }
  3865.         { Fire up the dialog box for configuring benchmarks }
  3866.         BEGIN
  3867.             dlgproc:=MakeProcInstance(@BenchConfigDialog, HInstance);
  3868.             DialogBox(HInstance,'BCONFDLG',HByteWin,dlgproc);
  3869.             FreeProcInstance(dlgproc);
  3870.         END;
  3871.  
  3872.   IDM_COMPINFO:                            { ** Display comparison information ** }
  3873.       BEGIN
  3874.         { We have to see if the comparison data file is available.
  3875.         If so,we can go ahead and display that dialog box.
  3876.         If not, throw up an alert dialog box. }
  3877.       IF iscompfilethere THEN
  3878.           BEGIN
  3879.                 dlgproc:=MakeProcInstance(@BenchCompDialog,HInstance);
  3880.               DialogBox(HInstance,'BCMPDLG',HByteWin,dlgproc);
  3881.               FreeProcInstance(dlgproc);
  3882.             END
  3883.           ELSE
  3884.           BEGIN
  3885.             ADTx:=28;
  3886.           ADTy:=20;
  3887.           StrCopy(@AlertDlgText,'Comparison Data File Not Found');
  3888.                     ADTCount:=StrLen(@AlertDlgText);
  3889.           dlgproc:=MakeProcInstance(@StandardalertDialog,HInstance);
  3890.           DialogBox(HInstance,'NOMEMDLG',HByteWin,dlgproc);
  3891.           FreeProcInstance(dlgproc);
  3892.         END;
  3893.       END;
  3894.     IDM_SYSCONF:              { ** Display system configuration ** }
  3895.         BEGIN
  3896.       InitBenchDisplay;
  3897.       logFileHeader( FALSE );
  3898.       CloseBenchDisplay;
  3899.         END;
  3900.  
  3901.     IDM_SETDEFS:              { ** Set to default configurations ** }
  3902.         BEGIN
  3903.             dlgproc:=MakeProcInstance(@SetToDefaultsDialog,HInstance);
  3904.             DialogBox(HInstance,'SDEFDLG',HByteWin,dlgproc);
  3905.             FreeProcInstance(dlgproc);
  3906.         END;
  3907.  
  3908.     IDM_EXECUTE:              { ** Execute benchmarks ** }
  3909.         BEGIN
  3910.             DoTests;              { Execute selected benchmarks }
  3911.             DisplayResults( TRUE, FALSE );                { Display results }
  3912.         END;
  3913.  END;    { CASE }
  3914. END;  { MainMenuProc }
  3915.  
  3916. (*
  3917. ** WINDOW HANDLING ROUTINES FOLLOW
  3918. *)
  3919. { ********************************************}
  3920. { WINDOW PROCEDURE FOR 'BYTEWB' WINDOW CLASS  }
  3921. FUNCTION ByteWinProc(Window: HWnd; Message, WParam: Word;
  3922.     LParam: Longint): Longint; export;
  3923.  
  3924. BEGIN
  3925.     ByteWinProc:=0;
  3926.  
  3927.     { Handle incoming messages }
  3928.     CASE Message OF
  3929.  
  3930.       wm_Create:
  3931.         BEGIN
  3932.       END;
  3933.  
  3934.       wm_Command:
  3935.         BEGIN
  3936.           MainMenuProc(WParam);                    { Handle menu stuff }
  3937.         Exit;
  3938.       END;
  3939.  
  3940.         wm_Destroy:
  3941.             BEGIN
  3942.                 PostQuitMessage(0);
  3943.                 Exit;
  3944.             END;
  3945.  
  3946.     END;  { CASE }
  3947.  
  3948.     { If we fall through to here...pass it along }
  3949.     ByteWinProc:=DefWindowProc(Window, Message, WParam, LParam);
  3950. END;
  3951.  
  3952. { *********************************************** }
  3953. { INITIALIZE FIRST INSTANCE                       }
  3954. { Initialize the first instance of the program.   }
  3955. {   1. Register all windows classes.              }
  3956. {   2. Create any objects we will ultimately use. }
  3957. PROCEDURE InitFirstInstance;
  3958. VAR
  3959.     ByteWinClass: TWndClass;
  3960. BEGIN
  3961.  
  3962.     { Ready our window class for registration }
  3963.     ByteWinClass.style:=cs_HRedraw OR cs_VRedraw;
  3964.     ByteWinClass.lpfnWndProc:=@ByteWinProc;
  3965.     ByteWinClass.cbClsExtra:=0;
  3966.     ByteWinClass.cbWndExtra:=0;
  3967.     ByteWinClass.hInstance:=HInstance;
  3968.     { ** NOTE: We should define our own ICON -- 7/9 RG }
  3969.     ByteWinClass.hIcon:=LoadIcon(HInstance,'WB1');
  3970.     ByteWinClass.hCursor:=LoadCursor(0,idc_Arrow);
  3971.     { ** NOTE: We should define a different color -- 7/9 RG }
  3972.     ByteWinClass.hbrBackground:=GetStockObject(Black_Brush);
  3973.     { ** NOTE: Need to define a menu for this class -- 7/9 RG }
  3974.     ByteWinClass.lpszMenuName:='BYTEMENU';
  3975.     ByteWinClass.lpszClassName:='BYTEWB';
  3976.  
  3977.     { ** NOTE: Must add better error handling -- 7/9 RG }
  3978.     IF (NOT RegisterClass(ByteWinClass))
  3979.     THEN  Halt(255);
  3980.  
  3981. END;    { InitFirstInstance }
  3982.  
  3983. { ******************************* }
  3984. { INITIALIZE ADDITIONAL INSTANCES }
  3985. PROCEDURE InitAddedInstance;
  3986.  
  3987. BEGIN
  3988. END;
  3989.  
  3990. { ************************ }
  3991. { INITIALIZE ALL INSTANCES }
  3992. PROCEDURE InitAllInstance;
  3993.  
  3994. BEGIN
  3995.     { Create a window }
  3996.   HByteWin:=CreateWindow('BYTEWB','BYTE Windows Benchmarks',
  3997.                           ws_OverlappedWindow,
  3998.               0,
  3999.               0,
  4000.               640,
  4001.               480,
  4002.               0,
  4003.               0,
  4004.               HInstance,
  4005.               NIL);
  4006.   ShowWindow(HByteWin, sw_Normal ); {sw_Maximize);}
  4007.   UpdateWindow(HByteWin);
  4008.  
  4009. END;
  4010.  
  4011. { ********************* }
  4012. { MAIN WINDOW PROCEDURE }
  4013. PROCEDURE WinMain;
  4014. VAR
  4015.     Message: TMsg;  { Message }
  4016.  
  4017. BEGIN
  4018.     { Initialize things properly }
  4019.     IF HPrevInst=0
  4020.     THEN
  4021.         InitFirstInstance
  4022.     ELSE
  4023.         InitAddedInstance;
  4024.  
  4025.     InitAllInstance;
  4026.     InitGlobals;
  4027.  
  4028.   if( autoLogAndExit )
  4029.   then begin
  4030.     doTests;
  4031.     DisplayResults( TRUE, FALSE );
  4032.     Halt( 0 );
  4033.   end;
  4034.   
  4035.     { Enter the main event loop }
  4036.     WHILE GetMessage(Message,0,0,0) DO
  4037.     BEGIN
  4038.         TranslateMessage(Message);
  4039.         DispatchMessage(Message);
  4040.     END;
  4041.     Halt(Message.wParam);
  4042. END;
  4043.  
  4044. { Here's the ... believe it or not ... heart }
  4045. { of the program.                            }
  4046. BEGIN
  4047.     WinMain;
  4048. END.
  4049.